diff --git a/HISTORY.md b/HISTORY.md index 3052ed8d..a485ad4b 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -12,6 +12,11 @@ http://visjs.org - Added visible property to the groups. - Added getLegend() method. +### Timeline + +- Fixed items in groups sometimes being displayed but not positioned correctly. + + ## 2014-07-22, version 3.1.0 diff --git a/dist/vis.js b/dist/vis.js index f0eb8d05..6453c023 100644 --- a/dist/vis.js +++ b/dist/vis.js @@ -81,40 +81,48 @@ 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 = { +<<<<<<< HEAD DataStep: __webpack_require__(38), 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), +>>>>>>> b6ed63dda6f296069050476eabc9b3a9e165069f 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) }, +<<<<<<< HEAD Component: __webpack_require__(22), CurrentTime: __webpack_require__(26), CustomTime: __webpack_require__(27), @@ -125,19 +133,31 @@ return /******/ (function(modules) { // webpackBootstrap 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) +>>>>>>> b6ed63dda6f296069050476eabc9b3a9e165069f } }; // 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 +166,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 +178,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 @@ -1368,2740 +1388,2642 @@ 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 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.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) { + 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 = {}; - - this._bubble(); + 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); + } - /************************************ - Helpers - ************************************/ - + addOrUpdate(item); + } + } + else if (data instanceof Object) { + // Single item + addOrUpdate(data); + } + else { + throw new Error('Unknown dataType'); + } - function extend(a, b) { - for (var i in b) { - if (b.hasOwnProperty(i)) { - a[i] = b[i]; - } - } + if (addedIds.length) { + this._trigger('add', {items: addedIds}, senderId); + } + if (updatedIds.length) { + this._trigger('update', {items: updatedIds}, senderId); + } - if (b.hasOwnProperty("toString")) { - a.toString = b.toString; - } + return addedIds.concat(updatedIds); + }; - if (b.hasOwnProperty("valueOf")) { - a.valueOf = b.valueOf; - } + /** + * 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; - return a; - } + // 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]; + } - function cloneMoment(m) { - var result = {}, i; - for (i in m) { - if (m.hasOwnProperty(i) && momentProperties.hasOwnProperty(i)) { - result[i] = m[i]; - } - } + // 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 result; + 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 + ')'); } - - function absRound(number) { - if (number < 0) { - return Math.ceil(number); - } else { - return Math.floor(number); - } + 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'; + } - // 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; + // build options + var type = options && options.type || this._options.type; + var filter = options && options.filter; + var items = [], item, itemId, i, len; - while (output.length < targetLength) { - output = '0' + output; + // 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); } - 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; + } } + } + else { + // get all items + if (order) { + // create an ordered list + items = []; + for (id in data) { + if (data.hasOwnProperty(id)) { + items.push(data[id]); + } + } - function daysInMonth(year, month) { - return new Date(Date.UTC(year, month + 1, 0)).getUTCDate(); - } + this._sort(items, order); - function weeksInYear(year, dow, doy) { - return weekOfYear(moment([year, 11, 31 + dow - doy]), dow, doy).week; + for (i = 0, len = items.length; i < len; i++) { + ids[i] = items[i][this._fieldId]; + } } - - function daysInYear(year) { - return isLeapYear(year) ? 366 : 365; + else { + // create unordered list + for (id in data) { + if (data.hasOwnProperty(id)) { + item = data[id]; + ids.push(item[this._fieldId]); + } + } } + } - function isLeapYear(year) { - return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; - } + return ids; + }; - 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; + /** + * 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; + }; - if (m._pf._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) { - overflow = DATE; - } + /** + * 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; - m._pf.overflow = overflow; + if (options && options.order) { + // execute forEach on ordered list + var items = this.get(options); + + 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); } + } } + } + }; - 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; + /** + * 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; - if (m._strict) { - m._isValid = m._isValid && - m._pf.charsLeftOver === 0 && - m._pf.unusedTokens.length === 0; - } - } - return m._isValid; + // 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)); + } } + } - function normalizeLanguage(key) { - return key ? key.toLowerCase().replace('_', '-') : key; - } + // order items + if (options && options.order) { + this._sort(mappedItems, options.order); + } - // 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(); - } + return mappedItems; + }; - /************************************ - Languages - ************************************/ + /** + * 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 = {}; + for (var field in item) { + if (item.hasOwnProperty(field) && (fields.indexOf(field) != -1)) { + filteredItem[field] = item[field]; + } + } - extend(Language.prototype, { + return 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; - } - } - }, + /** + * 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'); + } + }; - _months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"), - months : function (m) { - return this._months[m.month()]; - }, + /** + * 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; - _monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"), - monthsShort : function (m) { - return this._monthsShort[m.month()]; - }, + 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); + } + } - monthsParse : function (monthName) { - var i, mom, regex; + if (removedIds.length) { + this._trigger('remove', {items: removedIds}, senderId); + } - if (!this._monthsParse) { - this._monthsParse = []; - } + return removedIds; + }; - 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; - } - } - }, + /** + * 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; + }; - _weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"), - weekdays : function (m) { - return this._weekdays[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); - _weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"), - weekdaysShort : function (m) { - return this._weekdaysShort[m.day()]; - }, + this._data = {}; - _weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"), - weekdaysMin : function (m) { - return this._weekdaysMin[m.day()]; - }, + this._trigger('remove', {items: ids}, senderId); - weekdaysParse : function (weekdayName) { - var i, mom, regex; + return ids; + }; - if (!this._weekdaysParse) { - this._weekdaysParse = []; - } + /** + * 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; - 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; - } - } - }, + 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; + } + } + } - _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; - }, + return max; + }; - 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'); - }, + /** + * 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; - _meridiemParse : /[ap]\.?m?\.?/i, - meridiem : function (hours, minutes, isLower) { - if (hours > 11) { - return isLower ? 'pm' : 'PM'; - } else { - return isLower ? 'am' : 'AM'; - } - }, + 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; + } + } + } - _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; - }, + return min; + }; - _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; - }, - - _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. - }, - - _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]; - }; - - if (!key) { - return moment.fn._lang; - } + return values; + }; - if (!isArray(key)) { - //short-circuit everything else - lang = get(key); - if (lang) { - return lang; - } - key = [key]; - } + /** + * 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]; - //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; + 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; + } - /************************************ - Formatting - ************************************/ - - - function removeFormattingTokens(input) { - if (input.match(/\[[\s\S]/)) { - return input.replace(/^\[|\]$/g, ""); - } - return input.replace(/\\/g, ""); + 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; - function makeFormatFunction(format) { - var array = format.match(formattingTokens), i, length; + return id; + }; - for (i = 0, length = array.length; i < length; i++) { - if (formatTokenFunctions[array[i]]) { - array[i] = formatTokenFunctions[array[i]]; - } else { - array[i] = removeFormattingTokens(array[i]); - } - } + /** + * 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; - 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; - }; + // get the item from the dataset + var raw = this._data[id]; + if (!raw) { + return null; + } + + // 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; + }; - // format date using native date object - function formatMoment(m, format) { + /** + * 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'); + } - if (!m.isValid()) { - return m.lang().invalidDate(); - } + // 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 = expandFormat(format, m.lang()); + return id; + }; - if (!formatFunctions[format]) { - formatFunctions[format] = makeFormatFunction(format); - } + /** + * 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; + }; - return formatFunctions[format](m); - } + /** + * 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(); - function expandFormat(format, lang) { - var i = 5; + for (var col = 0, cols = columns.length; col < cols; col++) { + var field = columns[col]; + dataTable.setValue(row, col, item[field]); + } + }; - function replaceLongDateFormatTokens(input) { - return lang.longDateFormat(input) || input; - } + module.exports = DataSet; - localFormattingTokens.lastIndex = 0; - while (i >= 0 && localFormattingTokens.test(format)) { - format = format.replace(localFormattingTokens, replaceLongDateFormatTokens); - localFormattingTokens.lastIndex = 0; - i -= 1; - } - return format; - } +/***/ }, +/* 4 */ +/***/ function(module, exports, __webpack_require__) { + var util = __webpack_require__(1); + var DataSet = __webpack_require__(3); - /************************************ - Parsing - ************************************/ + /** + * 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 + var me = this; + this.listener = function () { + me._onEvent.apply(me, arguments); + }; - // 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; - } - } + this.setData(data); + } - 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]); + // TODO: implement a function .config() to dynamically update things like configured filter + // and trigger changes accordingly - return parts[0] === '+' ? -minutes : minutes; + /** + * Set a data source for the view + * @param {DataSet | DataView} data + */ + DataView.prototype.setData = function (data) { + var ids, i, len; + + 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__(45); + 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, { - - clone : function () { - return moment(this); - }, + /** + * 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; - valueOf : function () { - return +this._d + ((this._offset || 0) * 60000); - }, + var dataPoints = []; - unix : function () { - return Math.floor(+this / 1000); - }, + 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 - toString : function () { - return this.clone().lang('en').format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ"); - }, + // 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; - toDate : function () { - return this._offset ? new Date(+this) : this._d; - }, + if (dataX.indexOf(x) === -1) { + dataX.push(x); + } + if (dataY.indexOf(y) === -1) { + dataY.push(y); + } + } - 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]'); - } - }, + function sortNumber(a, b) { + return a - b; + } + dataX.sort(sortNumber); + dataY.sort(sortNumber); - toArray : function () { - var m = this; - return [ - m.year(), - m.month(), - m.date(), - m.hours(), - m.minutes(), - m.seconds(), - m.milliseconds() - ]; - }, + // 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; - isValid : function () { - return isValid(this); - }, + var xIndex = dataX.indexOf(x); // TODO: implement Array().indexOf() for Internet Explorer + var yIndex = dataY.indexOf(y); - isDSTShifted : function () { + if (dataMatrix[xIndex] === undefined) { + dataMatrix[xIndex] = []; + } - if (this._a) { - return this.isValid() && compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()) > 0; - } + var point3d = new Point3d(); + point3d.x = x; + point3d.y = y; + point3d.z = z; - return false; - }, + obj = {}; + obj.point = point3d; + obj.trans = undefined; + obj.screen = undefined; + obj.bottom = new Point3d(x, y, this.zMin); - parsingFlags : function () { - return extend({}, this._pf); - }, + dataMatrix[xIndex][yIndex] = obj; - invalidAt: function () { - return this._pf.overflow; - }, + dataPoints.push(obj); + } - utc : function () { - return this.zone(0); - }, + // 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; - local : function () { - this.zone(0); - this._isUTC = false; - return this; - }, + if (this.colValue !== undefined) { + point.value = data[i][this.colValue] || 0; + } - format : function (inputString) { - var output = formatMoment(this, inputString || moment.defaultFormat); - return this.lang().postformat(output); - }, + obj = {}; + obj.point = point; + obj.bottom = new Point3d(point.x, point.y, this.zMin); + obj.trans = undefined; + obj.screen = undefined; - 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; - }, + dataPoints.push(obj); + } + } - 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; - }, + return dataPoints; + }; - diff : function (input, units, asFloat) { - var that = makeAs(input, this), - zoneDiff = (this.zone() - that.zone()) * 6e4, - diff, output; + /** + * 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); + } - units = normalizeUnits(units); + this.frame = document.createElement('div'); + this.frame.style.position = 'relative'; + this.frame.style.overflow = 'hidden'; - 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); - }, + // 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); + } - from : function (time, withoutSuffix) { - return moment.duration(this.diff(time)).lang(this.lang()._abbr).humanize(!withoutSuffix); - }, + 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); - fromNow : function (withoutSuffix) { - return this.from(moment(), 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' - 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)); - }, + 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); - isLeapYear : function () { - return isLeapYear(this.year()); - }, + // add the new graph to the container element + this.containerElement.appendChild(this.frame); + }; - isDST : function () { - return (this.zone() < this.clone().month(0).zone() || - this.zone() < this.clone().month(5).zone()); - }, - 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; - } - }, + /** + * 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; - month : makeAccessor('Month', true), + this._resizeCanvas(); + }; - 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 */ - } + /** + * 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%'; - // weeks are a special case - if (units === 'week') { - this.weekday(0); - } else if (units === 'isoWeek') { - this.isoWeekday(1); - } + this.frame.canvas.width = this.frame.canvas.clientWidth; + this.frame.canvas.height = this.frame.canvas.clientHeight; - // quarters are also special - if (units === 'quarter') { - this.month(Math.floor(this.month() / 3) * 3); - } + // adjust with for margin + this.frame.filter.style.width = (this.frame.canvas.clientWidth - 2 * 10) + 'px'; + }; - return this; - }, + /** + * Start animation + */ + Graph3d.prototype.animationStart = function() { + if (!this.frame.filter || !this.frame.filter.slider) + throw 'No animation available'; - endOf: function (units) { - units = normalizeUnits(units); - return this.startOf(units).add((units === 'isoWeek' ? 'week' : units), 1).subtract('ms', 1); - }, + this.frame.filter.slider.play(); + }; - isAfter: function (input, units) { - units = typeof units !== 'undefined' ? units : 'millisecond'; - return +this.clone().startOf(units) > +moment(input).startOf(units); - }, - isBefore: 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; - isSame: function (input, units) { - units = units || 'ms'; - return +this.clone().startOf(units) === +makeAs(input, this).startOf(units); - }, + this.frame.filter.slider.stop(); + }; - 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; - } - ), - 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; - } - ), + /** + * 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 + } - // 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; - }, + // 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 + } + }; - zoneAbbr : function () { - return this._isUTC ? "UTC" : ""; - }, + /** + * 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; + } - zoneName : function () { - return this._isUTC ? "Coordinated Universal Time" : ""; - }, + if (pos.horizontal !== undefined && pos.vertical !== undefined) { + this.camera.setArmRotation(pos.horizontal, pos.vertical); + } - parseZone : function () { - if (this._tzm) { - this.zone(this._tzm); - } else if (typeof this._i === 'string') { - this.zone(this._i); - } - return this; - }, + if (pos.distance !== undefined) { + this.camera.setArmLength(pos.distance); + } - hasAlignedHourOffset : function (input) { - if (!input) { - input = 0; - } - else { - input = moment(input).zone(); - } + this.redraw(); + }; - 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(); +<<<<<<< HEAD /** * 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. @@ -4120,65 +4042,179 @@ return /******/ (function(modules) { // webpackBootstrap 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'; +>>>>>>> b6ed63dda6f296069050476eabc9b3a9e165069f + } + else { + ctx.textAlign = 'left'; + ctx.textBaseline = 'middle'; } - else { - // create a new element and add it to the SVG - element = document.createElement(elementType); - DOMContainer.appendChild(element); - } + 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 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 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 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 */ +<<<<<<< HEAD exports.drawBar = function (x, y, width, height, className, JSONcontainer, svgContainer) { // if (height != 0) { var rect = exports.getSVGElement('rect',JSONcontainer, svgContainer); @@ -4189,12496 +4225,11480 @@ return /******/ (function(modules) { // webpackBootstrap rect.setAttributeNS(null, "class", className); // } }; +======= + Graph3d.prototype._hsv2rgb = function(H, S, V) { + var R, G, B, C, Hi, X; +>>>>>>> b6ed63dda6f296069050476eabc9b3a9e165069f -/***/ }, -/* 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); - } - } - 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); + 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 (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); + // 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 { - // add new item - id = me._addItem(item); - addedIds.push(id); + size = dotSize; } - }; - if (Array.isArray(data)) { - // Array - for (var i = 0, len = data.length; i < len; i++) { - addOrUpdate(data[i]); + var radius; + if (this.showPerspective) { + radius = size / -point.trans.z; + } + else { + radius = size * -(this.eye.z / this.camera.getArmLength()); + } + 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? + + // 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; + + // 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; } - // determine the return type - var returnType; - if (options && options.returnType) { - var allowedValues = ["DataTable", "Array", "Object"]; - returnType = allowedValues.indexOf(options.returnType) == -1 ? "Array" : options.returnType; + // order the translated points by depth + var sortDepth = function (a, b) { + return b.dist - a.dist; + }; + this.dataPoints.sort(sortDepth); - 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 + ')'); + // 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]; + + // 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); } - if (returnType == 'DataTable' && !util.isDataTable(data)) { - throw new Error('Parameter "data" must be a DataTable ' + - 'when options.type is "DataTable"'); + 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); } - } - else if (data) { - returnType = (util.getType(data) == 'DataTable') ? 'DataTable' : 'Array'; - } - else { - returnType = 'Array'; - } - // build options - var type = options && options.type || this._options.type; - var filter = options && options.filter; - var items = [], item, itemId, i, len; + // 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); + } - // 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); - } - } - } - } + // 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)} + ]; - // order the results - if (options && options.order && id == undefined) { - this._sort(items, options.order); - } + // 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); + }); - // 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); - } - } - } + // 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; - // 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 { - // 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 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 { - // 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; - } + + // order the surfaces by their (translated) depth + surfaces.sort(function (a, b) { + var diff = b.dist - a.dist; + if (diff) return diff; + + // 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(); } } }; + /** - * 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 + * Draw a line through all datapoints. + * This function can be used when the style is 'line' */ - 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 = []; + Graph3d.prototype._redrawDataLine = function() { + var canvas = this.frame.canvas, + ctx = canvas.getContext('2d'), + point, i; - 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); - } - } - } + if (this.dataPoints === undefined || this.dataPoints.length <= 0) + return; // TODO: throw exception? - this._sort(items, order); + // 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); - 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]); - } - } - } - } + this.dataPoints[i].trans = trans; + this.dataPoints[i].screen = screen; } - 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); + // start the line + if (this.dataPoints.length > 0) { + point = this.dataPoints[0]; - 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]); - } - } - } + ctx.lineWidth = 1; // TODO: make customizable + ctx.strokeStyle = 'blue'; // TODO: make customizable + ctx.beginPath(); + ctx.moveTo(point.screen.x, point.screen.y); } - return ids; + // 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); + } + + // finish the line + if (this.dataPoints.length > 0) { + ctx.stroke(); + } }; /** - * Returns the DataSet itself. Is overwritten for example by the DataView, - * which returns the DataSet it is connected to instead. + * Start a moving operation inside the provided parent element + * @param {Event} event The event that occurred (required for + * retrieving the mouse position) */ - DataSet.prototype.getDataSet = function () { - return this; - }; + Graph3d.prototype._onMouseDown = function(event) { + event = event || window.event; - /** - * 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; + // check if mouse is still down (may be up when focus is lost for example + // in an iframe) + if (this.leftButtonDown) { + this._onMouseUp(event); + } - if (options && options.order) { - // execute forEach on ordered list - var items = this.get(options); + // only react on left mouse button down + this.leftButtonDown = event.which ? (event.which === 1) : (event.button === 1); + if (!this.leftButtonDown && !this.touchDown) return; - 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); - } - } - } - } + // 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); }; + /** - * 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 + * Perform moving operating. + * This function activated from within the funcion Graph.mouseDown(). + * @param {Event} event Well, eehh, the event */ - DataSet.prototype.map = function (callback, options) { - var filter = options && options.filter, - type = options && options.type || this._options.type, - mappedItems = [], - data = this._data, - item; + Graph3d.prototype._onMouseMove = function (event) { + event = event || window.event; - // 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)); - } - } + // calculate change in mouse position + var diffX = parseFloat(getMouseX(event)) - this.startMouseX; + var diffY = parseFloat(getMouseY(event)) - this.startMouseY; + + 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); + + // 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; } - // order items - if (options && options.order) { - this._sort(mappedItems, options.order); + // 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; } - return mappedItems; + this.camera.setArmRotation(horizontalNew, verticalNew); + this.redraw(); + + // fire a cameraPositionChange event + var parameters = this.getCameraPosition(); + this.emit('cameraPositionChange', parameters); + + util.preventDefault(event); }; + /** - * Filter the fields of an item - * @param {Object} item - * @param {String[]} fields Field names - * @return {Object} filteredItem - * @private + * Stop moving operating. + * This function activated from within the funcion Graph.mouseDown(). + * @param {event} event The event */ - DataSet.prototype._filterFields = function (item, fields) { - var filteredItem = {}; - - for (var field in item) { - if (item.hasOwnProperty(field) && (fields.indexOf(field) != -1)) { - filteredItem[field] = item[field]; - } - } + Graph3d.prototype._onMouseUp = function (event) { + this.frame.style.cursor = 'auto'; + this.leftButtonDown = false; - return filteredItem; + // remove event listeners here + util.removeEventListener(document, 'mousemove', this.onmousemove); + util.removeEventListener(document, 'mouseup', this.onmouseup); + util.preventDefault(event); }; /** - * Sort the provided array with items - * @param {Object[]} items - * @param {String | function} order A field name or custom sort function. - * @private + * 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._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); + 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; } - // 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'); + + if (this.tooltipTimeout) { + clearTimeout(this.tooltipTimeout); } - }; - /** - * 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; + // (delayed) display of a tooltip only if no mouse button is down + if (this.leftButtonDown) { + this._hideTooltip(); + return; + } - if (Array.isArray(id)) { - for (i = 0, len = id.length; i < len; i++) { - removedId = this._remove(id[i]); - if (removedId != null) { - removedIds.push(removedId); + 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(); } } } else { - removedId = this._remove(id); - if (removedId != null) { - removedIds.push(removedId); - } - } + // tooltip is currently not visible + var me = this; + this.tooltipTimeout = setTimeout(function () { + me.tooltipTimeout = null; - if (removedIds.length) { - this._trigger('remove', {items: removedIds}, senderId); + // show a tooltip if we have a data point + var dataPoint = me._dataPointFromXY(mouseX, mouseY); + if (dataPoint) { + me._showTooltip(dataPoint); + } + }, delay); } - - return removedIds; }; /** - * Remove an item by its id - * @param {Number | String | Object} id id or item - * @returns {Number | String | null} id - * @private + * Event handler for touchstart event on mobile devices */ - 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; + Graph3d.prototype._onTouchStart = function(event) { + this.touchDown = true; + + 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); + + this._onMouseDown(event); }; /** - * Clear the data - * @param {String} [senderId] Optional sender id - * @return {Array} removedIds The ids of all removed items + * Event handler for touchmove event on mobile devices */ - DataSet.prototype.clear = function (senderId) { - var ids = Object.keys(this._data); - - this._data = {}; - - this._trigger('remove', {items: ids}, senderId); - - return ids; + Graph3d.prototype._onTouchMove = function(event) { + this._onMouseMove(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 + * Event handler for touchend event on mobile devices */ - DataSet.prototype.max = function (field) { - var data = this._data, - max = null, - maxField = null; + Graph3d.prototype._onTouchEnd = function(event) { + this.touchDown = false; - 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; - } - } - } + util.removeEventListener(document, 'touchmove', this.ontouchmove); + util.removeEventListener(document, 'touchend', this.ontouchend); - return max; + this._onMouseUp(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 + * 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.min = function (field) { - var data = this._data, - min = null, - minField = null; + Graph3d.prototype._onWheel = function(event) { + if (!event) /* For IE. */ + event = window.event; - 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; - } - } + // 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; } - return min; - }; + // 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); - /** - * 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; + this.camera.setArmLength(newLength); + this.redraw(); - 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 (!exists && (value !== undefined)) { - values[count] = value; - count++; - } - } + this._hideTooltip(); } - if (fieldType) { - for (i = 0; i < values.length; i++) { - values[i] = util.convert(values[i], fieldType); - } - } + // fire a cameraPositionChange event + var parameters = this.getCameraPosition(); + this.emit('cameraPositionChange', parameters); - return values; + // 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); }; /** - * Add a single item. Will fail when an item with the same id already exists. - * @param {Object} item - * @return {String} id + * 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._addItem = function (item) { - var id = item[this._fieldId]; + Graph3d.prototype._insideTriangle = function (point, triangle) { + var a = triangle[0], + b = triangle[1], + c = triangle[2]; - 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; + function sign (x) { + return x > 0 ? 1 : x < 0 ? -1 : 0; } - 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; + 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)); - return id; + // 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); }; /** - * 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 + * 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._getItem = function (id, types) { - var field, value; - - // get the item from the dataset - var raw = this._data[id]; - if (!raw) { - return null; - } + Graph3d.prototype._dataPointFromXY = function (x, y) { + var i, + distMax = 100, // px + dataPoint = null, + closestDataPoint = null, + closestDist = null, + center = new Point2d(x, y); - // 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]); + 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 { - // no field types specified, no converting needed - for (field in raw) { - if (raw.hasOwnProperty(field)) { - value = raw[field]; - converted[field] = value; + // 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; + } } } } - return converted; + + + return closestDataPoint; }; /** - * 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 + * Display a tooltip for given data point + * @param {Object} dataPoint * @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) + ')'); + Graph3d.prototype._showTooltip = function (dataPoint) { + var content, line, dot; + + 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)'; + + line = document.createElement('div'); + line.style.position = 'absolute'; + line.style.height = '40px'; + line.style.width = '0'; + line.style.borderLeft = '1px solid #4d4d4d'; + + 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.tooltip = { + dataPoint: null, + dom: { + content: content, + line: line, + dot: dot + } + }; } - var d = this._data[id]; - if (!d) { - // item doesn't exist - throw new Error('Cannot update item: no item with id ' + id + ' found'); + else { + content = this.tooltip.dom.content; + line = this.tooltip.dom.line; + dot = this.tooltip.dom.dot; } - // 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); - } + this._hideTooltip(); + + 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 + '
'; } - return id; + content.style.left = '0'; + content.style.top = '0'; + this.frame.appendChild(content); + this.frame.appendChild(line); + this.frame.appendChild(dot); + + // calculate sizes + var contentWidth = content.offsetWidth; + var contentHeight = content.offsetHeight; + var lineHeight = line.offsetHeight; + var dotWidth = dot.offsetWidth; + var dotHeight = dot.offsetHeight; + + var left = dataPoint.screen.x - contentWidth / 2; + left = Math.min(Math.max(left, 10), this.frame.clientWidth - 10 - contentWidth); + + 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 an array with the column names of a Google DataTable - * @param {DataTable} dataTable - * @return {String[]} columnNames + * Hide the tooltip when displayed * @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._hideTooltip = function () { + if (this.tooltip) { + this.tooltip.dataPoint = null; + + 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); + } + } + } } - return columns; }; + /**--------------------------------------------------------------------------**/ + + /** - * Append an item as a row to the dataTable - * @param dataTable - * @param columns - * @param item - * @private + * Get the horizontal mouse position from a mouse event + * @param {Event} event + * @return {Number} mouse x */ - DataSet.prototype._appendRow = function (dataTable, columns, item) { - var row = dataTable.addRow(); + getMouseX = function(event) { + if ('clientX' in event) return event.clientX; + return event.targetTouches[0] && event.targetTouches[0].clientX || 0; + }; - for (var col = 0, cols = columns.length; col < cols; col++) { - var field = columns[col]; - dataTable.setValue(row, col, item[field]); - } + /** + * 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 = DataSet; + module.exports = Graph3d; /***/ }, -/* 8 */ +/* 6 */ /***/ function(module, exports, __webpack_require__) { - var util = __webpack_require__(1); - var DataSet = __webpack_require__(7); + var Point3d = __webpack_require__(9); /** - * 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 + * @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. * - * @constructor DataView + * Documentation: + * http://en.wikipedia.org/wiki/3D_projection */ - 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 - - var me = this; - this.listener = function () { - me._onEvent.apply(me, arguments); - }; + Camera = function () { + this.armLocation = new Point3d(); + this.armRotation = {}; + this.armRotation.horizontal = 0; + this.armRotation.vertical = 0; + this.armLength = 1.7; - this.setData(data); - } + this.cameraLocation = new Point3d(); + this.cameraRotation = new Point3d(0.5*Math.PI, 0, 0); - // TODO: implement a function .config() to dynamically update things like configured filter - // and trigger changes accordingly + this.calculateCameraOrientation(); + }; /** - * Set a data source for the view - * @param {DataSet | DataView} data + * 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.setData = function (data) { - var ids, i, len; + Camera.prototype.setArmLocation = function(x, y, z) { + this.armLocation.x = x; + this.armLocation.y = y; + this.armLocation.z = z; - if (this._data) { - // unsubscribe from current dataset - if (this._data.unsubscribe) { - this._data.unsubscribe('*', this.listener); - } + this.calculateCameraOrientation(); + }; - // 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}); + /** + * 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; } - this._data = data; - - if (this._data) { - // update fieldId - this._fieldId = this._options.fieldId || - (this._data && this._data.options && this._data.options.fieldId) || - 'id'; - - // 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}); + 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; + } - // subscribe to new dataset - if (this._data.on) { - this._data.on('*', this.listener); - } + if (horizontal !== undefined || vertical !== undefined) { + this.calculateCameraOrientation(); } }; /** - * 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 + * Retrieve the current arm rotation + * @return {object} An object with parameters horizontal and vertical */ - DataView.prototype.get = function (args) { - var me = this; - - // 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); - } - } - - // build up the call to the linked data set - var getArguments = []; - if (ids != undefined) { - getArguments.push(ids); - } - getArguments.push(viewOptions); - getArguments.push(data); + Camera.prototype.getArmRotation = function() { + var rot = {}; + rot.horizontal = this.armRotation.horizontal; + rot.vertical = this.armRotation.vertical; - return this._data && this._data.get.apply(this._data, getArguments); + return rot; }; /** - * 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 + * Set the (normalized) length of the camera arm. + * @param {Number} length A length between 0.71 and 5.0 */ - DataView.prototype.getIds = function (options) { - var ids; - - if (this._data) { - var defaultFilter = this._options.filter; - var filter; + Camera.prototype.setArmLength = function(length) { + if (length === undefined) + return; - if (options && options.filter) { - if (defaultFilter) { - filter = function (item) { - return defaultFilter(item) && options.filter(item); - } - } - else { - filter = options.filter; - } - } - else { - filter = defaultFilter; - } + this.armLength = length; - ids = this._data.getIds({ - filter: filter, - order: options && options.order - }); - } - else { - ids = []; - } + // 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; - return ids; + this.calculateCameraOrientation(); }; /** - * 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 + * Retrieve the arm length + * @return {Number} length */ - DataView.prototype.getDataSet = function () { - var dataSet = this; - while (dataSet instanceof DataView) { - dataSet = dataSet._data; - } - return dataSet || null; + Camera.prototype.getArmLength = function() { + return this.armLength; }; /** - * 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 + * Retrieve the camera location + * @return {Point3d} cameraLocation */ - 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 :-( - } - } - } - - break; - - 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); - } - } - - break; - } + Camera.prototype.getCameraLocation = function() { + return this.cameraLocation; + }; - 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); - } - } + /** + * Retrieve the camera rotation + * @return {Point3d} cameraRotation + */ + Camera.prototype.getCameraRotation = function() { + return this.cameraRotation; }; - // copy subscription functionality from DataSet - DataView.prototype.on = DataSet.prototype.on; - DataView.prototype.off = DataSet.prototype.off; - DataView.prototype._trigger = DataSet.prototype._trigger; + /** + * 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); - // 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; + // calculate rotation of the camera + this.cameraRotation.x = Math.PI/2 - this.armRotation.vertical; + this.cameraRotation.y = 0; + this.cameraRotation.z = -this.armRotation.horizontal; + }; - module.exports = DataView; + module.exports = Camera; /***/ }, -/* 9 */ +/* 7 */ /***/ function(module, exports, __webpack_require__) { - 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); + var DataView = __webpack_require__(4); /** - * @constructor Graph3d - * Graph3d displays data in 3d. - * - * Graph3d is developed in javascript as a Google Visualization Chart. + * @class Filter * - * @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] + * @param {DataSet} data The google data table + * @param {Number} column The index of the column to be filtered + * @param {Graph} graph The graph */ - function Graph3d(container, data, options) { - if (!(this instanceof Graph3d)) { - throw new SyntaxError('Constructor must be called with the new operator'); - } - - // 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%'; - - this.xLabel = 'x'; - this.yLabel = 'y'; - this.zLabel = 'z'; - this.filterLabel = 'time'; - this.legendLabel = 'value'; - - 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' + function Filter (data, column, graph) { + this.data = data; + this.column = column; + this.graph = graph; // the parent graph - this.animationInterval = 1000; // milliseconds - this.animationPreload = false; + this.index = undefined; + this.value = undefined; - this.camera = new Camera(); - this.eye = new Point3d(0, 0, -1); // TODO: set eye.z about 3/4 of the width of the window? + // read all distinct values and select the first one + this.values = graph.getDistinctValues(data.get(), this.column); - this.dataTable = null; // The original data table - this.dataPoints = null; // The table with point objects + // sort both numeric and string values correctly + this.values.sort(function (a, b) { + return a > b ? 1 : a < b ? -1 : 0; + }); - // the column indexes - this.colX = undefined; - this.colY = undefined; - this.colZ = undefined; - this.colValue = undefined; - this.colFilter = undefined; + if (this.values.length > 0) { + this.selectValue(0); + } - 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 + // create an array with the filtered datapoints. this will be loaded afterwards + this.dataPoints = []; - // constants - this.colorAxis = '#4D4D4D'; - this.colorGrid = '#D3D3D3'; - this.colorDot = '#7DC1FF'; - this.colorDotBorder = '#3267D2'; + this.loaded = false; + this.onLoadCallback = undefined; - // create a frame and canvas - this.create(); + if (graph.animationPreload) { + this.loaded = false; + this.loadInBackground(); + } + else { + this.loaded = true; + } + }; - // apply options (also when undefined) - this.setOptions(options); - // apply data - if (data) { - this.setData(data); - } - } + /** + * Return the label + * @return {string} label + */ + Filter.prototype.isLoaded = function() { + return this.loaded; + }; - // Extend Graph3d with an Emitter mixin - Emitter(Graph3d.prototype); /** - * Calculate the scaling values, dependent on the range in x, y, and z direction + * Return the loaded progress + * @return {Number} percentage between 0 and 100 */ - 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.getLoadedProgress = function() { + var len = this.values.length; - // 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; - } + var i = 0; + while (this.dataPoints[i]) { + i++; } - // scale the vertical axis - this.scale.z *= this.verticalRatio; - // TODO: can this be automated? verticalRatio? + return Math.round(i / len * 100); + }; - // 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); + /** + * Return the label + * @return {string} label + */ + Filter.prototype.getLabel = function() { + return this.graph.filterLabel; }; /** - * 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 columnIndex of the filter + * @return {Number} columnIndex */ - Graph3d.prototype._convert3Dto2D = function(point3d) { - var translation = this._convertPointToTranslation(point3d); - return this._convertTranslationToScreen(translation); + Filter.prototype.getColumn = function() { + return this.column; }; /** - * 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 currently selected value. Returns undefined if there is no selection + * @return {*} value */ - Graph3d.prototype._convertPointToTranslation = function(point3d) { - var ax = point3d.x * this.scale.x, - ay = point3d.y * this.scale.y, - az = point3d.z * this.scale.z, + Filter.prototype.getSelectedValue = function() { + if (this.index === undefined) + return undefined; - cx = this.camera.getCameraLocation().x, - cy = this.camera.getCameraLocation().y, - cz = this.camera.getCameraLocation().z, + return this.values[this.index]; + }; - // 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), + /** + * Retrieve all values of the filter + * @return {Array} values + */ + Filter.prototype.getValues = function() { + return this.values; + }; - // 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)); + /** + * Retrieve one value of the filter + * @param {Number} index + * @return {*} value + */ + Filter.prototype.getValue = function(index) { + if (index >= this.values.length) + throw 'Error: index out of range'; - return new Point3d(dx, dy, dz); + return this.values[index]; }; + /** - * 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 the (filtered) dataPoints for the currently selected filter index + * @param {Number} [index] (optional) + * @return {Array} dataPoints */ - 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; + Filter.prototype._getDataPoints = function(index) { + if (index === undefined) + index = this.index; - // calculate position on screen from translation - var bx; - var by; - if (this.showPerspective) { - bx = (dx - ex) * (ez / dz); - by = (dy - ey) * (ez / dz); + if (index === undefined) + return []; + + var dataPoints; + if (this.dataPoints[index]) { + dataPoints = this.dataPoints[index]; } else { - bx = dx * -(ez / this.camera.getArmLength()); - by = dy * -(ez / this.camera.getArmLength()); + 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; } - // 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 dataPoints; }; - /** - * 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 (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'; - } - this.frame.style.backgroundColor = fill; - this.frame.style.borderColor = stroke; - this.frame.style.borderWidth = strokeWidth + 'px'; - this.frame.style.borderStyle = 'solid'; + /** + * Set a callback function when the filter is fully loaded. + */ + Filter.prototype.setOnLoadCallback = function(callback) { + this.onLoadCallback = callback; }; - /// 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 - }; - /** - * 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 + '"'; + this.loaded = true; + + // remove the progress box + if (frame.progress !== undefined) { + frame.removeChild(frame.progress); + frame.progress = undefined; + } + + if (this.onLoadCallback) + this.onLoadCallback(); } }; - Graph3d.prototype.getNumberOfRows = function(data) { - return data.length; - } + module.exports = Filter; - Graph3d.prototype.getNumberOfColumns = function(data) { - var counter = 0; - for (var column in data[0]) { - if (data[0].hasOwnProperty(column)) { - counter++; - } - } - return counter; - } +/***/ }, +/* 8 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @prototype Point2d + * @param {Number} [x] + * @param {Number} [y] + */ + Point2d = function (x, y) { + this.x = x !== undefined ? x : 0; + this.y = y !== undefined ? y : 0; + }; + module.exports = Point2d; - 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; - } +/***/ }, +/* 9 */ +/***/ function(module, exports, __webpack_require__) { - 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; + /** + * @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; }; /** - * 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 + * Subtract the two provided points, returns a-b + * @param {Point3d} a + * @param {Point3d} b + * @return {Point3d} a-b */ - Graph3d.prototype._dataInitialize = function (rawData, style) { - var me = this; + 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; + }; - // unsubscribe from the dataTable - if (this.dataSet) { - this.dataSet.off('*', this._onChange); - } + /** + * 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; + }; - if (rawData === undefined) - return; + /** + * 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 + ); + }; - if (Array.isArray(rawData)) { - rawData = new DataSet(rawData); - } + /** + * 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(); - var data; - if (rawData instanceof DataSet || rawData instanceof DataView) { - data = rawData.get(); - } - else { - throw new Error('Array, DataSet, or DataView expected'); - } + 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; - if (data.length == 0) - return; + return crossproduct; + }; - this.dataSet = rawData; - this.dataTable = data; - // subscribe to changes in the dataset - this._onChange = function () { - me.setData(me.dataSet); - }; - this.dataSet.on('*', this._onChange); + /** + * 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 + ); + }; - // _determineColumnIndexes - // getNumberOfRows (points) - // getNumberOfColumns (x,y,z,v,t,t1,t2...) - // getDistinctValues (unique values?) - // getColumnRange + module.exports = 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'; +/***/ }, +/* 10 */ +/***/ function(module, exports, __webpack_require__) { + var util = __webpack_require__(1); - // 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();}); - } + /** + * @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.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); - var withBars = this.style == Graph3d.STYLE.BAR || - this.style == Graph3d.STYLE.BARCOLOR || - this.style == Graph3d.STYLE.BARSIZE; + this.frame.prev = document.createElement('INPUT'); + this.frame.prev.type = 'BUTTON'; + this.frame.prev.value = 'Prev'; + this.frame.appendChild(this.frame.prev); - // 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; - } + this.frame.play = document.createElement('INPUT'); + this.frame.play.type = 'BUTTON'; + this.frame.play.value = 'Play'; + this.frame.appendChild(this.frame.play); - if (this.defaultYBarWidth !== undefined) { - this.yBarWidth = this.defaultYBarWidth; - } - else { - var dataY = this.getDistinctValues(data,this.colY); - this.yBarWidth = (dataY[1] - dataY[0]) || 1; - } + 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);}; } - // calculate minimums and maximums - var xRange = this.getColumnRange(data,this.colX); - if (withBars) { - xRange.min -= this.xBarWidth / 2; - xRange.max += this.xBarWidth / 2; + this.onChangeCallback = undefined; + + this.values = []; + this.index = undefined; + + this.playTimeout = undefined; + this.playInterval = 1000; // milliseconds + this.playLoop = true; + } + + /** + * Select the previous index + */ + Slider.prototype.prev = function() { + var index = this.getIndex(); + if (index > 0) { + index--; + this.setIndex(index); } - 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; + }; - var yRange = this.getColumnRange(data,this.colY); - if (withBars) { - yRange.min -= this.yBarWidth / 2; - yRange.max += this.yBarWidth / 2; + /** + * Select the next index + */ + Slider.prototype.next = function() { + var index = this.getIndex(); + if (index < this.values.length - 1) { + index++; + this.setIndex(index); } - 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; + }; - 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; + /** + * Select the next index + */ + Slider.prototype.playNext = function() { + var start = new Date(); - 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; + 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); } - // set the scale dependent on the ranges. - this._setScale(); - }; + 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); + }; /** - * Filter the data based on the current filter - * @param {Array} data - * @return {Array} dataPoints Array with point objects which can be drawn on screen + * Toggle start or stop playing */ - 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.togglePlay = function() { + if (this.playTimeout === undefined) { + this.play(); + } else { + this.stop(); + } + }; - var dataPoints = []; + /** + * Start playing + */ + Slider.prototype.play = function() { + // Test whether already playing + if (this.playTimeout) return; - 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 + this.playNext(); - // 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 (this.frame) { + this.frame.play.value = 'Stop'; + } + }; - 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] = []; - } - - var point3d = new Point3d(); - point3d.x = x; - point3d.y = y; - point3d.z = z; - - obj = {}; - obj.point = point3d; - obj.trans = undefined; - obj.screen = undefined; - obj.bottom = new Point3d(x, y, this.zMin); - - dataMatrix[xIndex][yIndex] = obj; - - dataPoints.push(obj); - } - - // 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; - - if (this.colValue !== undefined) { - point.value = data[i][this.colValue] || 0; - } - - obj = {}; - obj.point = point; - obj.bottom = new Point3d(point.x, point.y, this.zMin); - obj.trans = undefined; - obj.screen = undefined; + /** + * Stop playing + */ + Slider.prototype.stop = function() { + clearInterval(this.playTimeout); + this.playTimeout = undefined; - dataPoints.push(obj); - } + if (this.frame) { + this.frame.play.value = 'Play'; } - - 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. + * Set a callback function which will be triggered when the value of the + * slider bar has changed. */ - 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'; - - // 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); - } - - 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); + Slider.prototype.setOnChangeCallback = function(callback) { + this.onChangeCallback = callback; }; - /** - * 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 the interval for playing the list + * @param {Number} interval The interval in milliseconds */ - Graph3d.prototype.setSize = function(width, height) { - this.frame.style.width = width; - this.frame.style.height = height; + Slider.prototype.setPlayInterval = function(interval) { + this.playInterval = interval; + }; - this._resizeCanvas(); + /** + * Retrieve the current play interval + * @return {Number} interval The interval in milliseconds + */ + Slider.prototype.getPlayInterval = function(interval) { + return this.playInterval; }; /** - * Resize the canvas to the current size of the frame + * 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._resizeCanvas = function() { - this.frame.canvas.style.width = '100%'; - this.frame.canvas.style.height = '100%'; + Slider.prototype.setPlayLoop = function(doLoop) { + this.playLoop = doLoop; + }; - 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'; + /** + * Execute the onchange callback function + */ + Slider.prototype.onChange = function() { + if (this.onChangeCallback !== undefined) { + this.onChangeCallback(); + } }; /** - * Start animation + * redraw the slider on the correct place */ - Graph3d.prototype.animationStart = function() { - if (!this.frame.filter || !this.frame.filter.slider) - throw 'No animation available'; + 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'; - this.frame.filter.slider.play(); + // position the slider button + var left = this.indexToLeft(this.index); + this.frame.slide.style.left = (left) + 'px'; + } }; /** - * Stop animation + * Set the list with values for the slider + * @param {Array} values A javascript array with values (any type) */ - Graph3d.prototype.animationStop = function() { - if (!this.frame.filter || !this.frame.filter.slider) return; + Slider.prototype.setValues = function(values) { + this.values = values; - this.frame.filter.slider.stop(); + if (this.values.length > 0) + this.setIndex(0); + else + this.index = undefined; }; - /** - * 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 + * Select a value by its index + * @param {Number} index */ - 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 - } + Slider.prototype.setIndex = function(index) { + if (index < this.values.length) { + this.index = index; - // 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); + this.redraw(); + this.onChange(); } else { - this.ycenter = parseFloat(this.defaultYCenter); // supposed to be in px + throw 'Error: index out of range'; } }; /** - * 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. + * retrieve the index of the currently selected vaue + * @return {Number} index */ - Graph3d.prototype.setCameraPosition = function(pos) { - if (pos === undefined) { - return; - } - - if (pos.horizontal !== undefined && pos.vertical !== undefined) { - this.camera.setArmRotation(pos.horizontal, pos.vertical); - } - - if (pos.distance !== undefined) { - this.camera.setArmLength(pos.distance); - } - - this.redraw(); + Slider.prototype.getIndex = function() { + return this.index; }; /** - * Retrieve the current camera rotation - * @return {object} An object with parameters horizontal, vertical, and - * distance + * retrieve the currently selected value + * @return {*} value */ - Graph3d.prototype.getCameraPosition = function() { - var pos = this.camera.getArmRotation(); - pos.distance = this.camera.getArmLength(); - return pos; + Slider.prototype.get = function() { + return this.values[this.index]; }; - /** - * Load data into the 3D Graph - */ - Graph3d.prototype._readData = function(data) { - // read the data - this._dataInitialize(data, this.style); + 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.startClientX = event.clientX; + this.startSlideX = parseFloat(this.frame.slide.style.left); - if (this.dataFilter) { - // apply filtering - this.dataPoints = this.dataFilter._getDataPoints(); - } - else { - // no filtering. load all data - this.dataPoints = this._getDataPoints(this.dataTable); - } + this.frame.style.cursor = 'move'; - // draw the filter - this._redrawFilter(); + // 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); }; - /** - * Replace the dataset of the Graph3d - * @param {Array | DataSet | DataView} data - */ - 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.leftToIndex = function (left) { + var width = parseFloat(this.frame.bar.style.width) - + this.frame.slide.clientWidth - 10; + var x = left - 3; - /** - * Update the options. Options will be merged with current options - * @param {Object} options - */ - Graph3d.prototype.setOptions = function (options) { - var cameraPosition = undefined; + 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; - this.animationStop(); + return index; + }; - if (options !== undefined) { - // retrieve parameter values - if (options.width !== undefined) this.width = options.width; - if (options.height !== undefined) this.height = options.height; + Slider.prototype.indexToLeft = function (index) { + var width = parseFloat(this.frame.bar.style.width) - + this.frame.slide.clientWidth - 10; - if (options.xCenter !== undefined) this.defaultXCenter = options.xCenter; - if (options.yCenter !== undefined) this.defaultYCenter = options.yCenter; + var x = index / (this.values.length-1) * width; + var left = x + 3; - 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; + return left; + }; - 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; - 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._onMouseMove = function (event) { + var diff = event.clientX - this.startClientX; + var x = this.startSlideX + diff; - 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 = this.leftToIndex(x); - if (options.cameraPosition !== undefined) cameraPosition = options.cameraPosition; + this.setIndex(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); - } - } + util.preventDefault(); + }; - this._setBackgroundColor(options && options.backgroundColor); - this.setSize(this.width, this.height); + Slider.prototype._onMouseUp = function (event) { + this.frame.style.cursor = 'auto'; - // re-load the data - if (this.dataTable) { - this.setData(this.dataTable); - } + // remove event listeners + util.removeEventListener(document, 'mousemove', this.onmousemove); + util.removeEventListener(document, 'mouseup', this.onmouseup); - // start animation when option is true - if (this.animationAutoStart && this.dataFilter) { - this.animationStart(); - } + util.preventDefault(); }; - /** - * Redraw the Graph. - */ - Graph3d.prototype.redraw = function() { - if (this.dataPoints === undefined) { - throw 'Error: graph data not initialized'; - } - - this._resizeCanvas(); - this._resizeCenter(); - this._redrawSlider(); - this._redrawClear(); - this._redrawAxis(); + module.exports = Slider; - 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._redrawInfo(); - this._redrawLegend(); - }; +/***/ }, +/* 11 */ +/***/ function(module, exports, __webpack_require__) { /** - * Clear the canvas before redrawing + * @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, ...) */ - Graph3d.prototype._redrawClear = function() { - var canvas = this.frame.canvas; - var ctx = canvas.getContext('2d'); + function StepNumber(start, end, step, prettyStep) { + // set default values + this._start = 0; + this._end = 0; + this._step = 1; + this.prettyStep = true; + this.precision = 5; - ctx.clearRect(0, 0, canvas.width, canvas.height); + this._current = 0; + this.setRange(start, end, step, prettyStep); }; - /** - * Redraw the legend showing the colors + * 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, ...) */ - Graph3d.prototype._redrawLegend = function() { - var y; - - if (this.style === Graph3d.STYLE.DOTCOLOR || - this.style === Graph3d.STYLE.DOTSIZE) { + StepNumber.prototype.setRange = function(start, end, step, prettyStep) { + this._start = start ? start : 0; + this._end = end ? end : 0; - 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 - } + this.setStep(step, prettyStep); + }; - 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; - } + /** + * 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; - var canvas = this.frame.canvas; - var ctx = canvas.getContext('2d'); - ctx.lineWidth = 1; - ctx.font = '14px arial'; // TODO: put in options + if (prettyStep !== undefined) + this.prettyStep = prettyStep; - 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); + if (this.prettyStep === true) + this._step = StepNumber.calculatePrettyStep(step); + else + this._step = step; + }; - //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); + /** + * 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 + */ + StepNumber.calculatePrettyStep = function (step) { + var log10 = function (x) {return Math.log(x) / Math.LN10;}; - ctx.strokeStyle = color; - ctx.beginPath(); - ctx.moveTo(left, top + y); - ctx.lineTo(right, top + y); - ctx.stroke(); - } + // 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))); - ctx.strokeStyle = this.colorAxis; - ctx.strokeRect(left, top, widthMax, height); - } + // 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; - 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(); + // for safety + if (prettyStep <= 0) { + prettyStep = 1; } - 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; - - ctx.beginPath(); - ctx.moveTo(left - gridLineLen, y); - ctx.lineTo(left, y); - ctx.stroke(); - - ctx.textAlign = 'right'; - ctx.textBaseline = 'middle'; - ctx.fillStyle = this.colorAxis; - ctx.fillText(step.getCurrent(), left - 2 * gridLineLen, y); - - step.next(); - } - - ctx.textAlign = 'right'; - ctx.textBaseline = 'top'; - var label = this.legendLabel; - ctx.fillText(label, right, bottom + this.margin); - } + return prettyStep; }; /** - * Redraw the filter + * returns the current value of the step + * @return {Number} current value */ - Graph3d.prototype._redrawFilter = function() { - this.frame.filter.innerHTML = ''; - - if (this.dataFilter) { - var options = { - 'visible': this.showAnimationControls - }; - var slider = new Slider(this.frame.filter, options); - this.frame.filter.slider = slider; - - // TODO: css here is not nice here... - this.frame.filter.style.padding = '10px'; - //this.frame.filter.style.backgroundColor = '#EFEFEF'; - - slider.setValues(this.dataFilter.values); - slider.setPlayInterval(this.animationInterval); - - // create an event handler - var me = this; - var onchange = function () { - var index = slider.getIndex(); - - me.dataFilter.selectValue(index); - me.dataPoints = me.dataFilter._getDataPoints(); + 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__(45); + 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__(!(function webpackMissingModule() { var e = new Error("Cannot find module \"./Core\""); e.code = 'MODULE_NOT_FOUND'; throw e; }())); + 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(); + // propagate options to all components + this.components.forEach(function (component) { + component.setOptions(options); + }); - // 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(); + // 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 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); - } + // redraw everything + this.redraw(); + }; - // 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); + /** + * Set items + * @param {vis.DataSet | Array | google.visualization.DataTable | null} items + */ + Timeline.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; + } + else { + // turn an array into a dataset + newDataSet = new DataSet(items, { + type: { + start: 'Date', + end: 'Date' + } + }); } - // 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); + // set items + this.itemsData = newDataSet; + this.itemSet && this.itemSet.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); } }; /** - * 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 groups + * @param {vis.DataSet | Array | google.visualization.DataTable} groups */ - Graph3d.prototype._hsv2rgb = function(H, S, V) { - var R, G, B, C, Hi, X; - - 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; + 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); } - return 'RGB(' + parseInt(R*255) + ',' + parseInt(G*255) + ',' + parseInt(B*255) + ')'; + 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); + }; /** - * Draw all datapoints as a grid - * This function can be used when the style is 'grid' + * Get the selected items by their id + * @return {Array} ids The ids of the selected items */ - 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.getSelection = function() { + return this.itemSet && this.itemSet.getSelection() || []; + }; - if (this.dataPoints === undefined || this.dataPoints.length <= 0) - return; // TODO: throw exception? + module.exports = Timeline; - // 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); - this.dataPoints[i].trans = trans; - this.dataPoints[i].screen = screen; +/***/ }, +/* 13 */ +/***/ function(module, exports, __webpack_require__) { - // 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; + var Emitter = __webpack_require__(45); + 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__(!(function webpackMissingModule() { var e = new Error("Cannot find module \"./Core\""); e.code = 'MODULE_NOT_FOUND'; throw e; }())); + var TimeAxis = __webpack_require__(27); + var CurrentTime = __webpack_require__(19); + var CustomTime = __webpack_require__(20); + var LineGraph = __webpack_require__(26); + + /** + * 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]; + } } - // sort the points on depth of their (x,y) position (not on z) - var sortDepth = function (a, b) { - return b.dist - a.dist; + var me = this; + this.defaultOptions = { + start: null, + end: null, + + autoResize: true, + + orientation: 'bottom', + width: null, + height: null, + maxHeight: null, + minHeight: null }; - this.dataPoints.sort(sortDepth); + this.options = util.deepExtend({}, this.defaultOptions); - 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; + // Create the DOM, props, and emitter + this._create(container); - if (point !== undefined && right !== undefined && top !== undefined && cross !== undefined) { + // all components listed here will be repainted automatically + this.components = []; - 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) + 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) + } + }; - topSideVisible = (crossproduct.z > 0); - } - else { - topSideVisible = true; - } + // range + this.range = new Range(this.body); + this.components.push(this.range); + this.body.range = this.range; - 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 + // time axis + this.timeAxis = new TimeAxis(this.body); + this.components.push(this.timeAxis); + this.body.util.snap = this.timeAxis.snap.bind(this.timeAxis); - 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; + // current time bar + this.currentTime = new CurrentTime(this.body); + this.components.push(this.currentTime); - if (point !== undefined) { - if (this.showPerspective) { - lineWidth = 2 / -point.trans.z; - } - else { - lineWidth = 2 * -(this.eye.z / this.camera.getArmLength()); - } - } + // 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 (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; + // item set + this.linegraph = new LineGraph(this.body); + this.components.push(this.linegraph); - 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(); - } + this.itemsData = null; // DataSet + this.groupsData = null; // DataSet - 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; + // apply options + if (options) { + this.setOptions(options); + } - 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(); - } - } + // IMPORTANT: THIS HAPPENS BEFORE SET ITEMS! + if (groups) { + this.setGroups(groups); } - }; + // create itemset + if (items) { + this.setItems(items); + } + else { + this.redraw(); + } + } /** - * Draw all datapoints as dots. - * This function can be used when the style is 'dot' or 'dot-line' + * 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._redrawDataDot = function() { - var canvas = this.frame.canvas; - var ctx = canvas.getContext('2d'); - var i; + 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); - if (this.dataPoints === undefined || this.dataPoints.length <= 0) - return; // TODO: throw exception? + // enable/disable autoResize + this._initAutoResize(); + } - // 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; + // propagate options to all components + this.components.forEach(function (component) { + component.setOptions(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; + // 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.'); } - // order the translated points by depth - var sortDepth = function (a, b) { - return b.dist - a.dist; - }; - this.dataPoints.sort(sortDepth); + // redraw everything + this.redraw(); + }; - // 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 (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(); - } + /** + * Set items + * @param {vis.DataSet | Array | google.visualization.DataTable | null} items + */ + Graph2d.prototype.setItems = function(items) { + var initialLoad = (this.itemsData == null); - // 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; - } + // 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' + } + }); + } - var radius; - if (this.showPerspective) { - radius = size / -point.trans.z; - } - else { - radius = size * -(this.eye.z / this.camera.getArmLength()); - } - if (radius < 0) { - radius = 0; - } + // set items + this.itemsData = newDataSet; + this.linegraph && this.linegraph.setItems(newDataSet); - 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); - } + if (initialLoad && ('start' in this.options || 'end' in this.options)) { + this.fit(); - // 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(); + 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); } }; /** - * Draw all datapoints as bars. - * This function can be used when the style is 'bar', 'bar-color', or 'bar-size' + * Set groups + * @param {vis.DataSet | Array | google.visualization.DataTable} groups */ - 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; - - // 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; + Graph2d.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); } - // order the translated points by depth - var sortDepth = function (a, b) { - return b.dist - a.dist; - }; - this.dataPoints.sort(sortDepth); - - // 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]; + this.groupsData = newDataSet; + this.linegraph.setGroups(newDataSet); + }; - // 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); - } - // 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); - } + module.exports = Graph2d; - // 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)} - ]; - // 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); - }); +/***/ }, +/* 14 */ +/***/ function(module, exports, __webpack_require__) { - // 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; + /** + * @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; - // 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}) - } + this.autoScale = true; + this.stepIndex = 0; + this.step = 1; + this.scale = 1; - // order the surfaces by their (translated) depth - surfaces.sort(function (a, b) { - var diff = b.dist - a.dist; - if (diff) return diff; + this.marginStart; + this.marginEnd; - // if equal depth, sort the top surface last - if (a.corners === top) return 1; - if (b.corners === top) return -1; + this.majorSteps = [1, 2, 5, 10]; + this.minorSteps = [0.25, 0.5, 1, 2]; - // both are equal - return 0; - }); + this.setRange(start, end, minimumStep, containerHeight, forcedStepSize); + } - // 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(); - } - } - }; /** - * Draw a line through all datapoints. - * This function can be used when the style is 'line' + * 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._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? + DataStep.prototype.setRange = function(start, end, minimumStep, containerHeight, forcedStepSize) { + this._start = start; + this._end = end; - // 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); + if (start == end) { + this._start = start - 0.75; + this._end = end + 1; + } - this.dataPoints[i].trans = trans; - this.dataPoints[i].screen = screen; + if (this.autoScale) { + this.setMinimumStep(minimumStep, containerHeight, forcedStepSize); } + this.setFirst(); + }; - // start the line - if (this.dataPoints.length > 0) { - point = this.dataPoints[0]; + /** + * Automatically determine the scale that bests fits the provided minimum step + * @param {Number} [minimumStep] The minimum step size in milliseconds + */ + 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); - ctx.lineWidth = 1; // TODO: make customizable - ctx.strokeStyle = 'blue'; // TODO: make customizable - ctx.beginPath(); - ctx.moveTo(point.screen.x, point.screen.y); - } + var minorStepIdx = -1; + var magnitudefactor = Math.pow(10,orderOfMagnitude); - // 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); + var start = 0; + if (orderOfMagnitude < 0) { + start = orderOfMagnitude; } - // finish the line - if (this.dataPoints.length > 0) { - ctx.stroke(); + 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; + } } + this.stepIndex = minorStepIdx; + this.scale = magnitudefactor; + this.step = magnitudefactor * this.minorSteps[minorStepIdx]; }; + /** - * Start a moving operation inside the provided parent element - * @param {Event} event The event that occurred (required for - * retrieving the mouse position) + * Set the range iterator to the start date. */ - 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; - - // 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); + DataStep.prototype.first = function() { + this.setFirst(); }; - /** - * Perform moving operating. - * This function activated from within the funcion Graph.mouseDown(). - * @param {Event} event Well, eehh, the event + * Round the current date to the first minor date value + * This must be executed once when the current date is set to start Date */ - 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; + DataStep.prototype.setFirst = function() { + var niceStart = this._start - (this.scale * this.minorSteps[this.stepIndex]); + var niceEnd = this._end + (this.scale * this.minorSteps[this.stepIndex]); - var horizontalNew = this.startArmRotation.horizontal + diffX / 200; - var verticalNew = this.startArmRotation.vertical + diffY / 200; + this.marginEnd = this.roundToMinor(niceEnd); + this.marginStart = this.roundToMinor(niceStart); + this.marginRange = this.marginEnd - this.marginStart; - var snapAngle = 4; // degrees - var snapValue = Math.sin(snapAngle / 360 * 2 * Math.PI); + this.current = this.marginEnd; - // 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; - } + }; - // snap vertically to nice angles - if (Math.abs(Math.sin(verticalNew)) < snapValue) { - verticalNew = Math.round((verticalNew / Math.PI)) * Math.PI; + 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]); } - if (Math.abs(Math.cos(verticalNew)) < snapValue) { - verticalNew = (Math.round((verticalNew/ Math.PI - 0.5)) + 0.5) * Math.PI; + else { + return rounded; } + } - this.camera.setArmRotation(horizontalNew, verticalNew); - this.redraw(); - - // fire a cameraPositionChange event - var parameters = this.getCameraPosition(); - this.emit('cameraPositionChange', parameters); - util.preventDefault(event); + /** + * Check if the there is a next step + * @return {boolean} true if the current date has not passed the end date + */ + DataStep.prototype.hasNext = function () { + return (this.current >= this.marginStart); }; - /** - * Stop moving operating. - * This function activated from within the funcion Graph.mouseDown(). - * @param {event} event The event + * Do the next step */ - Graph3d.prototype._onMouseUp = function (event) { - this.frame.style.cursor = 'auto'; - this.leftButtonDown = false; + DataStep.prototype.next = function() { + var prev = this.current; + this.current -= this.step; - // remove event listeners here - util.removeEventListener(document, 'mousemove', this.onmousemove); - util.removeEventListener(document, 'mouseup', this.onmouseup); - util.preventDefault(event); + // safety mechanism: if current time is still unchanged, move to the end + if (this.current == prev) { + this.current = this._end; + } }; /** - * 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 + * Do the next step */ - 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.previous = function() { + this.current += this.step; + this.marginEnd += this.step; + this.marginRange = this.marginEnd - this.marginStart; + }; - if (this.tooltipTimeout) { - clearTimeout(this.tooltipTimeout); - } - // (delayed) display of a tooltip only if no mouse button is down - if (this.leftButtonDown) { - this._hideTooltip(); - return; - } - 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(); - } + /** + * 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; } } - 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); - } + return toPrecision; }; + + /** - * Event handler for touchstart event on mobile devices + * 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 */ - Graph3d.prototype._onTouchStart = function(event) { - this.touchDown = true; - - 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); + DataStep.prototype.snap = function(date) { - this._onMouseDown(event); }; /** - * Event handler for touchmove event on mobile devices + * 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._onTouchMove = function(event) { - this._onMouseMove(event); + DataStep.prototype.isMajor = function() { + return (this.current % (this.scale * this.majorSteps[this.stepIndex]) == 0); }; - /** - * Event handler for touchend event on mobile devices - */ - Graph3d.prototype._onTouchEnd = function(event) { - this.touchDown = false; + module.exports = DataStep; - util.removeEventListener(document, 'touchmove', this.ontouchmove); - util.removeEventListener(document, 'touchend', this.ontouchend); - this._onMouseUp(event); - }; +/***/ }, +/* 15 */ +/***/ function(module, exports, __webpack_require__) { + var util = __webpack_require__(1); + var hammerUtil = __webpack_require__(42); + var moment = __webpack_require__(40); + var Component = __webpack_require__(18); /** - * Event handler for mouse wheel event, used to zoom the graph - * Code from http://adomas.org/javascript-mouse-wheel/ - * @param {event} event The event + * @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._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; - } - - // 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(); + 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._hideTooltip(); - } + this.body = body; - // fire a cameraPositionChange event - var parameters = this.getCameraPosition(); - this.emit('cameraPositionChange', parameters); + // 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); - // 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); - }; + this.props = { + touch: {} + }; - /** - * 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]; + // 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)); - function sign (x) { - return x > 0 ? 1 : x < 0 ? -1 : 0; - } + // ignore dragging when holding + this.body.emitter.on('hold', this._onHold.bind(this)); - 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)); + // mouse wheel for zooming + this.body.emitter.on('mousewheel', this._onMouseWheel.bind(this)); + this.body.emitter.on('DOMMouseScroll', this._onMouseWheel.bind(this)); // For FF - // 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); - }; + // 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(); /** - * 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 + * 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._dataPointFromXY = function (x, y) { - var i, - distMax = 100, // px - dataPoint = null, - closestDataPoint = null, - closestDist = null, - center = new Point2d(x, y); + 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 (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; - } - } - } + if ('start' in options || 'end' in options) { + // apply a new range. both start and end are optional + this.setRange(options.start, options.end); } } - 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; - } - } - } + /** + * Test whether direction has a valid value + * @param {String} direction 'horizontal' or 'vertical' + */ + function validateDirection (direction) { + if (direction != 'horizontal' && direction != 'vertical') { + throw new TypeError('Unknown direction "' + direction + '". ' + + 'Choose "horizontal" or "vertical".'); } + } - - return closestDataPoint; + /** + * 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); + } }; /** - * Display a tooltip for given data point - * @param {Object} dataPoint + * 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 */ - Graph3d.prototype._showTooltip = function (dataPoint) { - var content, line, dot; + 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 (!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)'; + // 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 + '"'); + } - line = document.createElement('div'); - line.style.position = 'absolute'; - line.style.height = '40px'; - line.style.width = '0'; - line.style.borderLeft = '1px solid #4d4d4d'; + // prevent start < end + if (newEnd < newStart) { + newEnd = newStart; + } - 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'; + // prevent start < min + if (min !== null) { + if (newStart < min) { + diff = (min - newStart); + newStart += diff; + newEnd += diff; - this.tooltip = { - dataPoint: null, - dom: { - content: content, - line: line, - dot: dot + // prevent end > max + if (max != null) { + if (newEnd > max) { + newEnd = max; + } } - }; - } - else { - content = this.tooltip.dom.content; - line = this.tooltip.dom.line; - dot = this.tooltip.dom.dot; + } } - this._hideTooltip(); + // prevent end > max + if (max !== null) { + if (newEnd > max) { + diff = (newEnd - max); + newStart -= diff; + newEnd -= diff; - 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 + '
'; + // prevent start < min + if (min != null) { + if (newStart < min) { + newStart = min; + } + } + } } - content.style.left = '0'; - content.style.top = '0'; - this.frame.appendChild(content); - this.frame.appendChild(line); - this.frame.appendChild(dot); - - // calculate sizes - var contentWidth = content.offsetWidth; - var contentHeight = content.offsetHeight; - var lineHeight = line.offsetHeight; - var dotWidth = dot.offsetWidth; - var dotHeight = dot.offsetHeight; - - var left = dataPoint.screen.x - contentWidth / 2; - left = Math.min(Math.max(left, 10), this.frame.clientWidth - 10 - contentWidth); - - 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'; - }; - - /** - * Hide the tooltip when displayed - * @private - */ - Graph3d.prototype._hideTooltip = function () { - if (this.tooltip) { - this.tooltip.dataPoint = null; + // 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; + } + } + } - 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); - } + // 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; } } } - }; - /**--------------------------------------------------------------------------**/ + var changed = (this.start != newStart || this.end != newEnd); + this.start = newStart; + this.end = newEnd; - /** - * 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; + return changed; }; /** - * Get the vertical mouse position from a mouse event - * @param {Event} event - * @return {Number} mouse y + * Retrieve the current range. + * @return {Object} An object with start and end properties */ - getMouseY = function(event) { - if ('clientY' in event) return event.clientY; - return event.targetTouches[0] && event.targetTouches[0].clientY || 0; + Range.prototype.getRange = function() { + return { + start: this.start, + end: this.end + }; }; - module.exports = Graph3d; - - -/***/ }, -/* 10 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * Expose `Emitter`. + * Calculate the conversion offset and scale for current range, based on + * the provided width + * @param {Number} width + * @returns {{offset: number, scale: number}} conversion */ - - module.exports = Emitter; + Range.prototype.conversion = function (width) { + return Range.conversion(this.start, this.end, width); + }; /** - * Initialize a new `Emitter`. - * - * @api public + * 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 */ - - function Emitter(obj) { - if (obj) return mixin(obj); + 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 + }; + } }; /** - * Mixin the emitter properties. - * - * @param {Object} obj - * @return {Object} - * @api private + * Start dragging horizontally or vertically + * @param {Event} event + * @private */ + Range.prototype._onDragStart = function(event) { + // only allow dragging when configured as movable + if (!this.options.moveable) return; - function mixin(obj) { - for (var key in Emitter.prototype) { - obj[key] = Emitter.prototype[key]; + // 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'; } - return obj; - } + }; /** - * Listen on the given `event` with `fn`. - * - * @param {String} event - * @param {Function} fn - * @return {Emitter} - * @api public + * Perform dragging operation + * @param {Event} event + * @private */ - - 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._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) + }); }; /** - * Adds an `event` listener that will be invoked a single - * time then automatically removed. - * - * @param {String} event - * @param {Function} fn - * @return {Emitter} - * @api public + * Stop dragging operation + * @param {event} event + * @private */ + Range.prototype._onDragEnd = function (event) { + // only allow dragging when configured as movable + if (!this.options.moveable) return; - Emitter.prototype.once = function(event, fn){ - var self = this; - this._callbacks = this._callbacks || {}; + // 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; - function on() { - self.off(event, on); - fn.apply(this, arguments); + if (this.body.dom.root) { + this.body.dom.root.style.cursor = 'auto'; } - on.fn = fn; - this.on(event, on); - return this; + // fire a rangechanged event + this.body.emitter.emit('rangechanged', { + start: new Date(this.start), + end: new Date(this.end) + }); }; /** - * Remove the given callback for `event` or all - * registered callbacks. - * - * @param {String} event - * @param {Function} fn - * @return {Emitter} - * @api public + * Event handler for mouse wheel event, used to zoom + * Code from http://adomas.org/javascript-mouse-wheel/ + * @param {Event} event + * @private */ + Range.prototype._onMouseWheel = function(event) { + // only allow zooming when configured as zoomable and moveable + if (!(this.options.zoomable && this.options.moveable)) return; - 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; - } - - // specific event - var callbacks = this._callbacks[event]; - if (!callbacks) return this; - - // remove all handlers - if (1 == arguments.length) { - delete this._callbacks[event]; - return this; + // 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; } - // 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; - }; + // 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 - /** - * Emit `event` with the given args. - * - * @param {String} event - * @param {Mixed} ... - * @return {Emitter} - */ + // 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)) ; + } - Emitter.prototype.emit = function(event){ - this._callbacks = this._callbacks || {}; - var args = [].slice.call(arguments, 1) - , callbacks = this._callbacks[event]; + // 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); - if (callbacks) { - callbacks = callbacks.slice(0); - for (var i = 0, len = callbacks.length; i < len; ++i) { - callbacks[i].apply(this, args); - } + this.zoom(scale, pointerDate); } - return this; + // Prevent default actions caused by mouse wheel + // (else the page and timeline both zoom and scroll) + event.preventDefault(); }; /** - * Return array of callbacks for `event`. - * - * @param {String} event - * @return {Array} - * @api public + * Start of a touch gesture + * @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; + }; - Emitter.prototype.listeners = function(event){ - this._callbacks = this._callbacks || {}; - return this._callbacks[event] || []; + /** + * On start of a hold gesture + * @private + */ + Range.prototype._onHold = function () { + this.props.touch.allowDragging = false; }; /** - * Check if this emitter has `event` handlers. - * - * @param {String} event - * @return {Boolean} - * @api public + * 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; - Emitter.prototype.hasListeners = function(event){ - return !! this.listeners(event).length; - }; + this.props.touch.allowDragging = false; + if (event.gesture.touches.length > 1) { + if (!this.props.touch.center) { + this.props.touch.center = getPointer(event.gesture.center, this.body.dom.center); + } -/***/ }, -/* 11 */ -/***/ function(module, exports, __webpack_require__) { + var scale = 1 / event.gesture.scale, + initDate = this._pointerToDate(this.props.touch.center); - /** - * @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; - }; + // 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); - /** - * 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; + // apply new range + this.setRange(newStart, newEnd); + } }; /** - * Add the two provided points, returns a+b - * @param {Point3d} a - * @param {Point3d} b - * @return {Point3d} a+b + * Helper function to calculate the center date for zooming + * @param {{x: Number, y: Number}} pointer + * @return {number} date + * @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._pointerToDate = function (pointer) { + var conversion; + var direction = this.options.direction; + + 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; + } }; /** - * Calculate the average of two 3d points - * @param {Point3d} a - * @param {Point3d} b - * @return {Point3d} The average, (a+b)/2 + * 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 */ - Point3d.avg = function(a, b) { - return new Point3d( - (a.x + b.x) / 2, - (a.y + b.y) / 2, - (a.z + b.z) / 2 - ); - }; + function getPointer (touch, element) { + return { + x: touch.pageX - util.getAbsoluteLeft(element), + y: touch.pageY - util.getAbsoluteTop(element) + }; + } /** - * 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 + * 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. */ - Point3d.crossProduct = function(a, b) { - var crossproduct = new Point3d(); + 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; + } - 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; + // calculate new start and end + var newStart = center + (this.start - center) * scale; + var newEnd = center + (this.end - center) * scale; - return crossproduct; + this.setRange(newStart, newEnd); }; - /** - * Rtrieve the length of the vector (or the distance from this point to the origin - * @return {Number} length + * 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 */ - Point3d.prototype.length = function() { - return Math.sqrt( - this.x * this.x + - this.y * this.y + - this.z * this.z - ); - }; + Range.prototype.move = function(delta) { + // zoom start Date and end Date relative to the centerDate + var diff = (this.end - this.start); - module.exports = Point3d; + // apply new values + var newStart = this.start + diff * delta; + var newEnd = this.end + diff * delta; + // TODO: reckon with min and max range -/***/ }, -/* 12 */ -/***/ function(module, exports, __webpack_require__) { + this.start = newStart; + this.end = newEnd; + }; /** - * @prototype Point2d - * @param {Number} [x] - * @param {Number} [y] + * Move the range to a new center point + * @param {Number} moveTo New center point of the range */ - Point2d = function (x, y) { - this.x = x !== undefined ? x : 0; - this.y = y !== undefined ? y : 0; + 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; + + this.setRange(newStart, newEnd); }; - module.exports = Point2d; + module.exports = Range; /***/ }, -/* 13 */ +/* 16 */ /***/ function(module, exports, __webpack_require__) { - var Point3d = __webpack_require__(11); + // Utility functions for ordering and stacking of items + var EPSILON = 0.001; // used when checking collisions, to prevent round-off errors /** - * @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 + * Order items by their start data + * @param {Item[]} items */ - 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(); + exports.orderByStart = function(items) { + items.sort(function (a, b) { + return a.data.start - b.data.start; + }); }; /** - * 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 + * Order items by their end date. If they have no end date, their start date + * is used. + * @param {Item[]} items */ - Camera.prototype.setArmLocation = function(x, y, z) { - this.armLocation.x = x; - this.armLocation.y = y; - this.armLocation.z = z; + 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; - this.calculateCameraOrientation(); + return aTime - bTime; + }); }; /** - * 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. + * 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 */ - Camera.prototype.setArmRotation = function(horizontal, vertical) { - if (horizontal !== undefined) { - this.armRotation.horizontal = horizontal; - } + exports.stack = function(items, margin, force) { + var i, iMax; - 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 (force) { + // reset top position of all items + for (i = 0, iMax = items.length; i < iMax; i++) { + items[i].top = null; + } } - if (horizontal !== undefined || vertical !== undefined) { - this.calculateCameraOrientation(); + // 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); + } } }; /** - * Retrieve the current arm rotation - * @return {object} An object with parameters horizontal and vertical + * 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. */ - Camera.prototype.getArmRotation = function() { - var rot = {}; - rot.horizontal = this.armRotation.horizontal; - rot.vertical = this.armRotation.vertical; + exports.nostack = function(items, margin) { + var i, iMax; - return rot; + // reset top position of all items + for (i = 0, iMax = items.length; i < iMax; i++) { + items[i].top = margin.axis; + } }; /** - * Set the (normalized) length of the camera arm. - * @param {Number} length A length between 0.71 and 5.0 + * 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 */ - Camera.prototype.setArmLength = function(length) { - if (length === undefined) - return; + 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); + }; - this.armLength = length; - // 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; +/***/ }, +/* 17 */ +/***/ function(module, exports, __webpack_require__) { - this.calculateCameraOrientation(); - }; + var moment = __webpack_require__(40); /** - * Retrieve the arm length - * @return {Number} length + * @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 */ - Camera.prototype.getArmLength = function() { - return this.armLength; + 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; + + // 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 }; + /** - * Retrieve the camera location - * @return {Point3d} cameraLocation + * 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 */ - Camera.prototype.getCameraLocation = function() { - return this.cameraLocation; + 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); + } }; /** - * Retrieve the camera rotation - * @return {Point3d} cameraRotation + * Set the range iterator to the start date. */ - Camera.prototype.getCameraRotation = function() { - return this.cameraRotation; + TimeStep.prototype.first = function() { + this.current = new Date(this._start.valueOf()); + this.roundToMinor(); }; /** - * Calculate the location and rotation of the camera based on the - * position and orientation of the camera arm + * Round the current date to the first minor date value + * This must be executed once when the current date is set to start Date */ - 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); + 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 + } - // calculate rotation of the camera - this.cameraRotation.x = Math.PI/2 - this.armRotation.vertical; - this.cameraRotation.y = 0; - this.cameraRotation.z = -this.armRotation.horizontal; + 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; + } + } }; - 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 + * Check if the there is a next step + * @return {boolean} true if the current date has not passed the end date */ - function Filter (data, column, graph) { - this.data = data; - this.column = column; - this.graph = graph; // the parent graph - - this.index = undefined; - this.value = undefined; + TimeStep.prototype.hasNext = function () { + return (this.current.valueOf() <= this._end.valueOf()); + }; - // read all distinct values and select the first one - this.values = graph.getDistinctValues(data.get(), this.column); + /** + * Do the next step + */ + TimeStep.prototype.next = function() { + var prev = this.current.valueOf(); - // sort both numeric and string values correctly - this.values.sort(function (a, b) { - return a > b ? 1 : a < b ? -1 : 0; - }); + // 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: - if (this.values.length > 0) { - this.selectValue(0); + 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; + } + } + 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; + } } - // 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(); + 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; + } } - else { - this.loaded = true; + + // safety mechanism: if current time is still unchanged, move to the end + if (this.current.valueOf() == prev) { + this.current = new Date(this._end.valueOf()); } }; /** - * Return the label - * @return {string} label + * Get the current datetime + * @return {Date} current The current date */ - Filter.prototype.isLoaded = function() { - return this.loaded; + TimeStep.prototype.getCurrent = function() { + return this.current; }; - /** - * Return the loaded progress - * @return {Number} percentage between 0 and 100 + * 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. */ - Filter.prototype.getLoadedProgress = function() { - var len = this.values.length; + TimeStep.prototype.setScale = function(newScale, newStep) { + this.scale = newScale; - var i = 0; - while (this.dataPoints[i]) { - i++; + if (newStep > 0) { + this.step = newStep; } - return Math.round(i / len * 100); + this.autoScale = false; }; - /** - * Return the label - * @return {string} label + * Enable or disable autoscaling + * @param {boolean} enable If true, autoascaling is set true */ - Filter.prototype.getLabel = function() { - return this.graph.filterLabel; + TimeStep.prototype.setAutoScale = function (enable) { + this.autoScale = enable; }; /** - * Return the columnIndex of the filter - * @return {Number} columnIndex - */ - Filter.prototype.getColumn = function() { - return this.column; - }; - - /** - * Return the currently selected value. Returns undefined if there is no selection - * @return {*} value + * Automatically determine the scale that bests fits the provided minimum step + * @param {Number} [minimumStep] The minimum step size in milliseconds */ - Filter.prototype.getSelectedValue = function() { - if (this.index === undefined) - return undefined; + TimeStep.prototype.setMinimumStep = function(minimumStep) { + if (minimumStep == undefined) { + return; + } - return this.values[this.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); - /** - * Retrieve all values of the filter - * @return {Array} values - */ - Filter.prototype.getValues = function() { - return this.values; + // 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;} }; /** - * Retrieve one value of the filter - * @param {Number} index - * @return {*} value + * 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 */ - Filter.prototype.getValue = function(index) { - if (index >= this.values.length) - throw 'Error: index out of range'; + TimeStep.prototype.snap = function(date) { + var clone = new Date(date.valueOf()); - return this.values[index]; - }; - - - /** - * Retrieve the (filtered) dataPoints for the currently selected filter index - * @param {Number} [index] (optional) - * @return {Array} dataPoints - */ - 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]; + 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 { - 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); + 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.dataPoints[index] = dataPoints; + clone.setHours(0); + clone.setMinutes(0); + clone.setSeconds(0); + clone.setMilliseconds(0); } - - return dataPoints; + 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; }; - - /** - * Set a callback function when the filter is fully loaded. + * 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. */ - Filter.prototype.setOnLoadCallback = function(callback) { - this.onLoadCallback = callback; + 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; + } }; /** - * Add a value to the list with available values for this filter - * No double entries will be created. - * @param {Number} index + * 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 */ - Filter.prototype.selectValue = function(index) { - if (index >= this.values.length) - throw 'Error: index out of range'; + TimeStep.prototype.getLabelMinor = function(date) { + if (date == undefined) { + date = this.current; + } - this.index = index; - this.value = this.values[index]; + 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 ''; + } }; + /** - * Load all filtered rows in the background one by one - * Start this method without providing an index! + * 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 */ - Filter.prototype.loadInBackground = function(index) { - if (index === undefined) - index = 0; - - var frame = this.graph.frame; - - 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; + TimeStep.prototype.getLabelMajor = function(date) { + if (date == undefined) { + date = this.current; } - else { - this.loaded = true; - - // remove the progress box - if (frame.progress !== undefined) { - frame.removeChild(frame.progress); - frame.progress = undefined; - } - if (this.onLoadCallback) - this.onLoadCallback(); + //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 = Filter; + module.exports = TimeStep; /***/ }, -/* 15 */ +/* 18 */ /***/ function(module, exports, __webpack_require__) { - var util = __webpack_require__(1); + /** + * 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; + } /** - * @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. + * Set options for the component. The new options will be merged into the + * current options. + * @param {Object} options */ - 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); - - // 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);}; + Component.prototype.setOptions = function(options) { + if (options) { + util.extend(this.options, options); } - - this.onChangeCallback = undefined; - - this.values = []; - this.index = undefined; - - this.playTimeout = undefined; - this.playInterval = 1000; // milliseconds - this.playLoop = true; - } + }; /** - * Select the previous index + * Repaint the component + * @return {boolean} Returns true if the component is resized */ - Slider.prototype.prev = function() { - var index = this.getIndex(); - if (index > 0) { - index--; - this.setIndex(index); - } + Component.prototype.redraw = function() { + // should be implemented by the component + return false; }; /** - * Select the next index + * Destroy the component. Cleanup DOM and event listeners */ - Slider.prototype.next = function() { - var index = this.getIndex(); - if (index < this.values.length - 1) { - index++; - this.setIndex(index); - } + Component.prototype.destroy = function() { + // should be implemented by the component }; /** - * Select the next index + * 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.playNext = function() { - var start = new Date(); + Component.prototype._isResized = function() { + var resized = (this.props._previousWidth !== this.props.width || + this.props._previousHeight !== this.props.height); - 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); - } + this.props._previousWidth = this.props.width; + this.props._previousHeight = this.props.height; - var end = new Date(); - var diff = (end - start); + return resized; + }; - // 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 + module.exports = Component; - var me = this; - this.playTimeout = setTimeout(function() {me.playNext();}, interval); - }; - /** - * Toggle start or stop playing - */ - Slider.prototype.togglePlay = function() { - if (this.playTimeout === undefined) { - this.play(); - } else { - this.stop(); - } - }; +/***/ }, +/* 19 */ +/***/ function(module, exports, __webpack_require__) { + + var util = __webpack_require__(1); + var Component = __webpack_require__(18); /** - * Start playing + * 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.play = function() { - // Test whether already playing - if (this.playTimeout) return; + function CurrentTime (body, options) { + this.body = body; - this.playNext(); + // default options + this.defaultOptions = { + showCurrentTime: true + }; + this.options = util.extend({}, this.defaultOptions); - if (this.frame) { - this.frame.play.value = 'Stop'; - } - }; + this._create(); - /** - * Stop playing - */ - Slider.prototype.stop = function() { - clearInterval(this.playTimeout); - this.playTimeout = undefined; + this.setOptions(options); + } - if (this.frame) { - this.frame.play.value = 'Play'; - } - }; + CurrentTime.prototype = new Component(); /** - * Set a callback function which will be triggered when the value of the - * slider bar has changed. + * Create the HTML DOM for the current time bar + * @private */ - Slider.prototype.setOnChangeCallback = function(callback) { - this.onChangeCallback = callback; + 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.bar = bar; }; /** - * Set the interval for playing the list - * @param {Number} interval The interval in milliseconds + * Destroy the CurrentTime bar */ - Slider.prototype.setPlayInterval = function(interval) { - this.playInterval = interval; + 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 current play interval - * @return {Number} interval The interval in milliseconds + * Set options for the component. Options will be merged in current options. + * @param {Object} options Available parameters: + * {boolean} [showCurrentTime] */ - Slider.prototype.getPlayInterval = function(interval) { - return this.playInterval; + CurrentTime.prototype.setOptions = function(options) { + if (options) { + // copy all options that we know + util.selectiveExtend(['showCurrentTime'], 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; - }; + 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(); + } - /** - * Execute the onchange callback function - */ - Slider.prototype.onChange = function() { - if (this.onChangeCallback !== undefined) { - this.onChangeCallback(); + 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(); } + + return false; }; /** - * redraw the slider on the correct place + * Start auto refreshing the current time bar */ - 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'; + CurrentTime.prototype.start = function() { + var me = this; - // position the slider button - var left = this.indexToLeft(this.index); - this.frame.slide.style.left = (left) + 'px'; - } - }; + 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; - /** - * Set the list with values for the slider - * @param {Array} values A javascript array with values (any type) - */ - Slider.prototype.setValues = function(values) { - this.values = values; + me.redraw(); - if (this.values.length > 0) - this.setIndex(0); - else - this.index = undefined; + // start a timer to adjust for the new time + me.currentTimeTimer = setTimeout(update, interval); + } + + update(); }; /** - * Select a value by its index - * @param {Number} index + * Stop auto refreshing the current time bar */ - Slider.prototype.setIndex = function(index) { - if (index < this.values.length) { - this.index = index; - - this.redraw(); - this.onChange(); - } - else { - throw 'Error: index out of range'; + CurrentTime.prototype.stop = function() { + if (this.currentTimeTimer !== undefined) { + clearTimeout(this.currentTimeTimer); + delete this.currentTimeTimer; } }; - /** - * retrieve the index of the currently selected vaue - * @return {Number} index - */ - Slider.prototype.getIndex = function() { - return this.index; - }; + module.exports = CurrentTime; + + +/***/ }, +/* 20 */ +/***/ function(module, exports, __webpack_require__) { + var Hammer = __webpack_require__(41); + var util = __webpack_require__(1); + var Component = __webpack_require__(18); /** - * retrieve the currently selected value - * @return {*} value + * A custom time bar + * @param {{range: Range, dom: Object}} body + * @param {Object} [options] Available parameters: + * {Boolean} [showCustomTime] + * @constructor CustomTime + * @extends Component */ - Slider.prototype.get = function() { - return this.values[this.index]; - }; + function CustomTime (body, options) { + this.body = body; - 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; + // default options + this.defaultOptions = { + showCustomTime: false + }; + this.options = util.extend({}, this.defaultOptions); - this.startClientX = event.clientX; - this.startSlideX = parseFloat(this.frame.slide.style.left); + this.customTime = new Date(); + this.eventParams = {}; // stores state parameters while dragging the bar - this.frame.style.cursor = 'move'; + // create the DOM + this._create(); - // 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); - }; + this.setOptions(options); + } + CustomTime.prototype = new Component(); - Slider.prototype.leftToIndex = function (left) { - var width = parseFloat(this.frame.bar.style.width) - - this.frame.slide.clientWidth - 10; - var x = left - 3; + /** + * Set options for the component. Options will be merged in current options. + * @param {Object} options Available parameters: + * {boolean} [showCustomTime] + */ + CustomTime.prototype.setOptions = function(options) { + if (options) { + // copy all options that we know + util.selectiveExtend(['showCustomTime'], this.options, options); + } + }; - 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; + /** + * Create the DOM for the custom time + * @private + */ + 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; - return index; + 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)); }; - Slider.prototype.indexToLeft = function (index) { - var width = parseFloat(this.frame.bar.style.width) - - this.frame.slide.clientWidth - 10; + /** + * Destroy the CustomTime bar + */ + CustomTime.prototype.destroy = function () { + this.options.showCustomTime = false; + this.redraw(); // will remove the bar from the DOM - var x = index / (this.values.length-1) * width; - var left = x + 3; + this.hammer.enable(false); + this.hammer = null; - return left; + this.body = null; }; + /** + * Repaint the component + * @return {boolean} Returns true if the component is resized + */ + 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); + } + var x = this.body.util.toScreen(this.customTime); - Slider.prototype._onMouseMove = function (event) { - var diff = event.clientX - this.startClientX; - var x = this.startSlideX + diff; + 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); + } + } - var index = this.leftToIndex(x); + return false; + }; - this.setIndex(index); + /** + * Set custom time. + * @param {Date} time + */ + CustomTime.prototype.setCustomTime = function(time) { + this.customTime = new Date(time.valueOf()); + this.redraw(); + }; - util.preventDefault(); + /** + * Retrieve the current custom time. + * @return {Date} customTime + */ + CustomTime.prototype.getCustomTime = function() { + return new Date(this.customTime.valueOf()); }; + /** + * Start moving horizontally + * @param {Event} event + * @private + */ + CustomTime.prototype._onDragStart = function(event) { + this.eventParams.dragging = true; + this.eventParams.customTime = this.customTime; - Slider.prototype._onMouseUp = function (event) { - this.frame.style.cursor = 'auto'; + event.stopPropagation(); + event.preventDefault(); + }; - // remove event listeners - util.removeEventListener(document, 'mousemove', this.onmousemove); - util.removeEventListener(document, 'mouseup', this.onmouseup); + /** + * Perform moving operating. + * @param {Event} event + * @private + */ + CustomTime.prototype._onDrag = function (event) { + if (!this.eventParams.dragging) return; - util.preventDefault(); - }; + var deltaX = event.gesture.deltaX, + x = this.body.util.toScreen(this.eventParams.customTime) + deltaX, + time = this.body.util.toTime(x); - module.exports = Slider; + this.setCustomTime(time); + // fire a timechange event + this.body.emitter.emit('timechange', { + time: new Date(this.customTime.valueOf()) + }); -/***/ }, -/* 16 */ -/***/ function(module, exports, __webpack_require__) { + event.stopPropagation(); + event.preventDefault(); + }; /** - * @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, ...) + * Stop moving operating. + * @param {event} event + * @private */ - 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._onDragEnd = function (event) { + if (!this.eventParams.dragging) return; - /** - * 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; + // fire a timechanged event + this.body.emitter.emit('timechanged', { + time: new Date(this.customTime.valueOf()) + }); - this.setStep(step, prettyStep); + event.stopPropagation(); + event.preventDefault(); }; - /** - * 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; + module.exports = CustomTime; - if (prettyStep !== undefined) - this.prettyStep = prettyStep; - if (this.prettyStep === true) - this._step = StepNumber.calculatePrettyStep(step); - else - this._step = step; - }; +/***/ }, +/* 21 */ +/***/ function(module, exports, __webpack_require__) { + + var util = __webpack_require__(1); + var DOMutil = __webpack_require__(2); + var Component = __webpack_require__(18); + var DataStep = __webpack_require__(14); /** - * 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 + * A horizontal time axis + * @param {Object} [options] See DataAxis.setOptions for the available + * options. + * @constructor DataAxis + * @extends Component + * @param body */ - StepNumber.calculatePrettyStep = function (step) { - var log10 = function (x) {return Math.log(x) / Math.LN10;}; + function DataAxis (body, options, svg) { + this.id = util.randomUUID(); + this.body = body; - // 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))); + 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 + }; - // 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; + this.linegraphSVG = svg; + this.props = {}; + this.DOMelements = { // dynamic elements + lines: {}, + labels: {} + }; - // for safety - if (prettyStep <= 0) { - prettyStep = 1; - } + this.dom = {}; - return prettyStep; - }; + this.range = {start:0, end:0}; - /** - * returns the current value of the step - * @return {Number} current value - */ - StepNumber.prototype.getCurrent = function () { - return parseFloat(this._current.toPrecision(this.precision)); - }; + this.options = util.extend({}, this.defaultOptions); + this.conversionFactor = 1; - /** - * returns the current step size - * @return {Number} current step size - */ - StepNumber.prototype.getStep = function () { - return this._step; - }; + this.setOptions(options); + this.width = Number(('' + this.options.width).replace("px","")); + this.minWidth = this.width; + this.height = this.linegraphSVG.offsetHeight; - /** - * Set the current value to the largest value smaller than start, which - * is a multiple of the step size - */ - StepNumber.prototype.start = function() { - this._current = this._start - this._start % this._step; - }; + this.stepPixels = 25; + this.stepPixelsForced = 25; + this.lineOffset = 0; + this.master = true; + this.svgElements = {}; - /** - * Do a step, add the step size to the current value - */ - StepNumber.prototype.next = function () { - this._current += this._step; - }; - /** - * Returns true whether the end is reached - * @return {boolean} True if the current value has passed the end value. - */ - StepNumber.prototype.end = function () { - return (this._current > this._end); - }; + this.groups = {}; + this.amountOfGroups = 0; - module.exports = StepNumber; + // create the HTML DOM + this._create(); + } + DataAxis.prototype = new Component(); -/***/ }, -/* 17 */ -/***/ 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); - /** - * 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 - */ - 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]; - } + DataAxis.prototype.addGroup = function(label, graphOptions) { + if (!this.groups.hasOwnProperty(label)) { + this.groups[label] = graphOptions; } + this.amountOfGroups += 1; + }; - if (!(this instanceof Timeline)) { - throw new SyntaxError('Constructor must be called with the new operator'); + DataAxis.prototype.updateGroup = function(label, graphOptions) { + this.groups[label] = graphOptions; + }; + + DataAxis.prototype.removeGroup = function(label) { + if (this.groups.hasOwnProperty(label)) { + delete this.groups[label]; + this.amountOfGroups -= 1; } + }; - var me = this; - this.defaultOptions = { - start: null, - end: null, - autoResize: true, + 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); - orientation: 'bottom', - width: null, - height: null, - maxHeight: null, - minHeight: null - }; - this.options = util.deepExtend({}, this.defaultOptions); + this.minWidth = Number(('' + this.options.width).replace("px","")); - // 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) + if (redraw == true && this.dom.frame) { + this.hide(); + this.show(); } - }; - - // 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); + /** + * 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; - // 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.dom.lineContainer = document.createElement('div'); + this.dom.lineContainer.style.width = '100%'; + this.dom.lineContainer.style.height = this.height; - // item set - this.itemSet = new ItemSet(this.body); - this.components.push(this.itemSet); + // 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); + }; - this.itemsData = null; // DataSet - this.groupsData = null; // DataSet + DataAxis.prototype._redrawGroupIcons = function () { + DOMutil.prepareElements(this.svgElements); - // apply options - if (options) { - this.setOptions(options); - } + var x; + var iconWidth = this.options.iconWidth; + var iconHeight = 15; + var iconOffset = 4; + var y = iconOffset + 0.5 * iconHeight; - // create itemset - if (items) { - this.setItems(items); + if (this.options.orientation == 'left') { + x = iconOffset; } else { - this.redraw(); - } - } - - /** - * 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); - - // enable/disable autoResize - this._initAutoResize(); + x = this.width - iconWidth - iconOffset; } - // 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.'); + for (var groupId in this.groups) { + if (this.groups.hasOwnProperty(groupId)) { + this.groups[groupId].drawIcon(x, y, this.svgElements, this.svg, iconWidth, iconHeight); + y += iconHeight + iconOffset; + } } - // redraw everything - this.redraw(); + DOMutil.cleanupElements(this.svgElements); }; /** - * Set items - * @param {vis.DataSet | Array | google.visualization.DataTable | null} items + * Create the HTML DOM for the DataAxis */ - Timeline.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; - } - else { - // turn an array into a dataset - newDataSet = new DataSet(items, { - type: { - start: 'Date', - end: 'Date' - } - }); + 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); + } } - // set items - this.itemsData = newDataSet; - this.itemSet && this.itemSet.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.dom.lineContainer.parentNode) { + this.body.dom.backgroundHorizontal.appendChild(this.dom.lineContainer); } }; /** - * 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.hide = function() { + if (this.dom.frame.parentNode) { + this.dom.frame.parentNode.removeChild(this.dom.frame); } - this.groupsData = newDataSet; - this.itemSet.setGroups(newDataSet); + if (this.dom.lineContainer.parentNode) { + this.dom.lineContainer.parentNode.removeChild(this.dom.lineContainer); + } }; /** - * 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. + * Set a range (start and end) + * @param end + * @param start + * @param end */ - Timeline.prototype.setSelection = function(ids) { - this.itemSet && this.itemSet.setSelection(ids); + DataAxis.prototype.setRange = function (start, end) { + this.range.start = start; + this.range.end = end; }; /** - * Get the selected items by their id - * @return {Array} ids The ids of the selected items + * Repaint the component + * @return {boolean} Returns true if the component is resized */ - Timeline.prototype.getSelection = function() { - return this.itemSet && this.itemSet.getSelection() || []; - }; + DataAxis.prototype.redraw = function () { + var changeCalled = false; + if (this.amountOfGroups == 0) { + this.hide(); + } + else { + this.show(); + this.height = Number(this.linegraphSVG.style.height.replace("px","")); + // svg offsetheight did not work in firefox and explorer... + this.dom.lineContainer.style.height = this.height + 'px'; + this.width = this.options.visible == true ? Number(('' + this.options.width).replace("px","")) : 0; - module.exports = Timeline; + var props = this.props; + var frame = this.dom.frame; + // update classname + frame.className = 'dataaxis'; -/***/ }, -/* 18 */ -/***/ function(module, exports, __webpack_require__) { + // calculate character width and height + this._calculateCharSize(); - // 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.'); - } - } + var orientation = this.options.orientation; + var showMinorLabels = this.options.showMinorLabels; + var 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; -/***/ }, -/* 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 */ + 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; - (function(window, undefined) { - 'use strict'; + // 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; + }; /** - * @main - * @module hammer - * - * @class Hammer - * @static + * Repaint major and minor text labels and vertical grid lines + * @private */ + DataAxis.prototype._redrawLabels = function () { + DOMutil.prepareElements(this.DOMelements); - /** - * 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 || {}); - }; + var orientation = this.options['orientation']; - /** - * version, as defined in package.json - * the value will be set at each build - * @property VERSION - * @final - * @type {String} - */ - Hammer.VERSION = '1.1.3'; + // 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(); - /** - * 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', + // get the distance in pixels for a step + var stepPixels = this.dom.frame.offsetHeight / ((step.marginRange / step.step) + 1); + this.stepPixels = stepPixels; - /** - * 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', + var amountOfSteps = this.height / stepPixels; + var stepDifference = 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', + 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; + } - /** - * Specifies whether zooming is enabled. Used by IE10> - * @property defaults.behavior.contentZooming - * @type {String} - * @default 'none' - */ - contentZooming: 'none', - /** - * 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', + this.valueAtZero = step.marginEnd; + var marginStartPos = 0; - /** - * 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)' + // do not draw the first label + var max = 1; + step.next(); + + this.maxLabelSize = 0; + var y = 0; + while (max < Math.round(amountOfSteps)) { + + y = Math.round(max * stepPixels); + marginStartPos = max * stepPixels; + var isMajor = step.isMajor(); + + 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); } - }; - /** - * hammer document where the base events are added at - * @property DOCUMENT - * @type {HTMLElement} - * @default window.document - */ - Hammer.DOCUMENT = document; + if (isMajor && this.options['showMajorLabels'] && this.master == true || + this.options['showMinorLabels'] == false && this.master == false && isMajor == true) { - /** - * detect support for pointer events - * @property HAS_POINTEREVENTS - * @type {Boolean} - */ - Hammer.HAS_POINTEREVENTS = navigator.pointerEnabled || navigator.msPointerEnabled; + 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); + } - /** - * detect support for touch events - * @property HAS_TOUCHEVENTS - * @type {Boolean} - */ - Hammer.HAS_TOUCHEVENTS = ('ontouchstart' in window); + step.next(); + max++; + } - /** - * detect mobile browsers - * @property IS_MOBILE - * @type {Boolean} - */ - Hammer.IS_MOBILE = /mobile|tablet|ip(ad|hone|od)|android|silk/i.test(navigator.userAgent); + this.conversionFactor = marginStartPos/((amountOfSteps-1) * step.step); - /** - * 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 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); + 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); + this.redraw(); + return true; + } + else { + DOMutil.cleanupElements(this.DOMelements); + return false; + } + }; /** - * interval in which Hammer recalculates current velocity/direction/angle in ms - * @property CALCULATE_INTERVAL - * @type {Number} - * @default 25 + * Create a label for the axis at position x + * @private + * @param y + * @param text + * @param orientation + * @param className + * @param characterHeight */ - Hammer.CALCULATE_INTERVAL = 25; + DataAxis.prototype._redrawLabel = function (y, text, orientation, className, characterHeight) { + // reuse redundant label + var label = DOMutil.getDOMElement('div',this.DOMelements, this.dom.frame); //this.dom.redundant.labels.shift(); + label.className = className; + label.innerHTML = text; - /** - * 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 = {}; + 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"; + } - /** - * 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'; + label.style.top = y - 0.5 * characterHeight + this.options.labelOffsetY + 'px'; - /** - * 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'; + text += ''; - /** - * 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'; + var largestWidth = Math.max(this.props.majorCharWidth,this.props.minorCharWidth); + if (this.maxLabelSize < text.length * largestWidth) { + this.maxLabelSize = text.length * largestWidth; + } + }; /** - * if the window events are set... - * @property READY - * @writeOnce - * @type {Boolean} - * @default false + * Create a minor line for the axis at position y + * @param y + * @param orientation + * @param className + * @param offset + * @param width */ - Hammer.READY = false; + DataAxis.prototype._redrawLine = function (y, orientation, className, offset, width) { + if (this.master == true) { + var line = DOMutil.getDOMElement('div',this.DOMelements, this.dom.lineContainer);//this.dom.redundant.lines.shift(); + line.className = className; + line.innerHTML = ''; - /** - * plugins namespace - * @property plugins - * @type {Object} - */ - Hammer.plugins = Hammer.plugins || {}; + 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'; + } + }; + + + 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 + }; - /** - * gestures namespace - * see `/gestures` for the definitions - * @property gestures - * @type {Object} - */ - Hammer.gestures = Hammer.gestures || {}; /** - * setup events to detect gestures on the document - * this function is called when creating an new instance + * 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 */ - function setup() { - if(Hammer.READY) { - return; - } + DataAxis.prototype._calculateCharSize = function () { + // determine the char width and height on the minor axis + if (!('minorCharHeight' in this.props)) { - // find what eventtypes we add listeners to - Event.determineEventTypes(); + var textMinor = document.createTextNode('0'); + var measureCharMinor = document.createElement('DIV'); + measureCharMinor.className = 'yAxis minor measure'; + measureCharMinor.appendChild(textMinor); + this.dom.frame.appendChild(measureCharMinor); - // Register all gestures inside Hammer.gestures - Utils.each(Hammer.gestures, function(gesture) { - Detection.register(gesture); - }); + this.props.minorCharHeight = measureCharMinor.clientHeight; + this.props.minorCharWidth = measureCharMinor.clientWidth; - // Add touch events on the document - Event.onTouch(Hammer.DOCUMENT, EVENT_MOVE, Detection.detect); - Event.onTouch(Hammer.DOCUMENT, EVENT_END, Detection.detect); + this.dom.frame.removeChild(measureCharMinor); + } - // Hammer is ready...! - Hammer.READY = true; - } + 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); + } + }; /** - * @module hammer - * - * @class Utils - * @static + * 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 */ - 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; - }, - - /** - * 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); - }, + DataAxis.prototype.snap = function(date) { + return this.step.snap(date); + }; - /** - * 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); - }, + module.exports = DataAxis; - /** - * 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; - // 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; - } - } - } - }, +/***/ }, +/* 22 */ +/***/ function(module, exports, __webpack_require__) { - /** - * 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; - }, + var util = __webpack_require__(1); + var DOMutil = __webpack_require__(2); - /** - * 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; - } - }, + /** + * @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'] + 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 = []; + } - /** - * 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); - }, + 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 = []; + } + }; - /** - * 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; - }, + GraphGroup.prototype.setZeroPosition = function(pos) { + this.zeroPosition = pos; + }; - /** - * 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; + GraphGroup.prototype.setOptions = function(options) { + if (options !== undefined) { + var fields = ['sampling','style','sort','yAxisOrientation','barChart']; + util.selectiveDeepExtend(fields, this.options, options); - // 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 - }; + util.mergeOptions(this.options, options,'catmullRom'); + util.mergeOptions(this.options, options,'drawPoints'); + util.mergeOptions(this.options, options,'shaded'); + + 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; + } } + } + } + } + }; - Utils.each(touches, function(touch) { - pageX.push(touch.pageX); - pageY.push(touch.pageY); - clientX.push(touch.clientX); - clientY.push(touch.clientY); - }); + 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.setOptions(group.options); + }; - 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 - }; - }, + GraphGroup.prototype.drawIcon = function(x, y, JSONcontainer, SVGcontainer, iconWidth, iconHeight) { + var fillHeight = iconHeight * 0.5; + var path, fillPath; - /** - * 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 - }; - }, + 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"); - /** - * 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; + 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"); + } - return Math.atan2(y, x) * 180 / Math.PI; - }, + 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); - /** - * 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); + var offset = Math.round((iconWidth - (2 * barWidth))/3); - if(x >= y) { - return touch1.clientX - touch2.clientX > 0 ? DIRECTION_LEFT : DIRECTION_RIGHT; - } - return touch1.clientY - touch2.clientY > 0 ? DIRECTION_UP : DIRECTION_DOWN; - }, + 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); + } + }; - /** - * 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; + module.exports = GraphGroup; - 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; - }, +/***/ }, +/* 23 */ +/***/ function(module, exports, __webpack_require__) { - /** - * 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; - }, + var util = __webpack_require__(1); + var stack = __webpack_require__(16); + var ItemRange = __webpack_require__(31); - /** - * 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; - }, + /** + * @constructor Group + * @param {Number | String} groupId + * @param {Object} data + * @param {ItemSet} itemSet + */ + function Group (groupId, data, itemSet) { + this.groupId = groupId; - /** - * 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); + this.itemSet = itemSet; - 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); - } + this.dom = {}; + this.props = { + label: { + width: 0, + height: 0 + } + }; + this.className = null; - // test the style - if(p in element.style) { - element.style[p] = (toggle == null || toggle) && value || ''; - break; - } - } - }, + 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: [] + }; - /** - * 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; - } + this._create(); - // set the css properties - Utils.each(props, function(value, prop) { - Utils.setPrefixedCss(element, prop, value, toggle); - }); + this.setData(data); + } - var falseFn = toggle && function() { - return false; - }; + /** + * Create DOM elements for the group + * @private + */ + Group.prototype._create = function() { + var label = document.createElement('div'); + label.className = 'vlabel'; + this.dom.label = label; - // also the disable onselectstart - if(props.userSelect == 'none') { - element.onselectstart = falseFn; - } - // and disable ondragstart - if(props.userDrag == 'none') { - element.ondragstart = falseFn; - } - }, + var inner = document.createElement('div'); + inner.className = 'inner'; + label.appendChild(inner); + this.dom.inner = inner; - /** - * 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(); - }); - } - }; + var foreground = document.createElement('div'); + foreground.className = 'group'; + foreground['timeline-group'] = this; + this.dom.foreground = foreground; + + this.dom.background = document.createElement('div'); + this.dom.background.className = 'group'; + + this.dom.axis = document.createElement('div'); + this.dom.axis.className = 'group'; + // create a hidden marker to detect when the Timelines container is attached + // to the DOM, or the style of a parent of the Timeline is changed from + // display:none is changed to visible. + this.dom.marker = document.createElement('div'); + this.dom.marker.style.visibility = 'hidden'; + this.dom.marker.innerHTML = '?'; + this.dom.background.appendChild(this.dom.marker); + }; /** - * @module hammer + * 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) { + this.dom.inner.innerHTML = content; + } + else { + this.dom.inner.innerHTML = this.groupId; + } + + // update title + this.dom.label.title = data && data.title || ''; + + if (!this.dom.inner.firstChild) { + util.addClassName(this.dom.inner, 'hidden'); + } + else { + util.removeClassName(this.dom.inner, 'hidden'); + } + + // 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); + } + }; + /** - * @class Event - * @static + * Get the width of the group label + * @return {number} width */ - 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, + Group.prototype.getLabelWidth = function() { + return this.props.label.width; + }; - /** - * if EVENT_START has been fired - * @property started - * @private - * @type {Boolean} - */ - started: false, - /** - * when the mouse is hold down, this is true - * @property should_detect - * @private - * @type {Boolean} - */ - shouldDetect: false, + /** + * 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; - /** - * 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); - }); - }, + this.visibleItems = this._updateVisibleItems(this.orderedItems, this.visibleItems, range); - /** - * 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); - }); - }, + // 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; - /** - * 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; + util.forEach(this.items, function (item) { + item.dirty = true; + if (item.displayed) item.redraw(); + }); - var onTouchHandler = function onTouchHandler(ev) { - var srcType = ev.type.toLowerCase(), - isPointer = Hammer.HAS_POINTEREVENTS, - isMouse = Utils.inStr(srcType, 'mouse'), - triggerType; + restack = true; + } - // 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; + // 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); + } - // 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; - } + // 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); - // update the pointer event before entering the detection - if(isPointer && eventType != EVENT_END) { - PointerEvent.updatePointer(eventType, ev); - } + // 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; - // we are in a touch/down state, so allowed detection of gestures - if(self.shouldDetect) { - triggerType = self.doDetect.call(self, ev, eventType, element, handler); - } + // 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; - // ...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 - } + // apply new height + this.dom.background.style.height = height + 'px'; + this.dom.foreground.style.height = height + 'px'; + this.dom.label.style.height = height + 'px'; - if(isPointer && eventType == EVENT_END) { - PointerEvent.updatePointer(eventType, 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(); + } - this.on(element, EVENT_TYPES[eventType], onTouchHandler); - return onTouchHandler; - }, + return resized; + }; - /** - * 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; + /** + * Show this group: attach to the DOM + */ + Group.prototype.show = function() { + if (!this.dom.label.parentNode) { + this.itemSet.dom.labelSet.appendChild(this.dom.label); + } - // 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.dom.foreground.parentNode) { + this.itemSet.dom.foreground.appendChild(this.dom.foreground); + } - // keep track of how many touches have been removed - changedLength = touchList.length - ((ev.changedTouches) ? ev.changedTouches.length : 1); - } + if (!this.dom.background.parentNode) { + this.itemSet.dom.background.appendChild(this.dom.background); + } - // 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; - } + if (!this.dom.axis.parentNode) { + this.itemSet.dom.axis.appendChild(this.dom.axis); + } + }; - // detection has been started, we keep track of this, see above - this.started = true; + /** + * Hide this group: remove from the DOM + */ + Group.prototype.hide = function() { + var label = this.dom.label; + if (label.parentNode) { + label.parentNode.removeChild(label); + } - // generate some event data, some basic information - var evData = this.collectEventData(element, triggerType, touchList, ev); + var foreground = this.dom.foreground; + if (foreground.parentNode) { + foreground.parentNode.removeChild(foreground); + } - // 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); - } + var background = this.dom.background; + if (background.parentNode) { + background.parentNode.removeChild(background); + } - // trigger a change (TOUCH, RELEASE) event, this means the length of the touches changed - if(triggerChange) { - evData.changedLength = changedLength; - evData.eventType = triggerChange; + var axis = this.dom.axis; + if (axis.parentNode) { + axis.parentNode.removeChild(axis); + } + }; - handler.call(Detection, evData); + /** + * Add an item to the group + * @param {Item} item + */ + Group.prototype.add = function(item) { + this.items[item.id] = item; + item.setParent(this); - evData.eventType = triggerType; - delete evData.changedLength; - } + 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); + } + }; - // trigger the END event - if(triggerType == EVENT_END) { - handler.call(Detection, evData); + /** + * Remove an item from the group + * @param {Item} item + */ + Group.prototype.remove = function(item) { + delete this.items[item.id]; + item.setParent(this.itemSet); - // ...and we are done with the detection - // so reset everything to start each detection totally fresh - this.started = false; - } + // remove from visible items + var index = this.visibleItems.indexOf(item); + if (index != -1) this.visibleItems.splice(index, 1); - return triggerType; - }, + // TODO: also remove from ordered items? + }; - /** - * 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' - ]; - } - - EVENT_TYPES[EVENT_START] = types[0]; - EVENT_TYPES[EVENT_MOVE] = types[1]; - EVENT_TYPES[EVENT_END] = types[2]; - return EVENT_TYPES; - }, - - /** - * 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; - } - - var identifiers = []; - var concat = [].concat(Utils.toArray(ev.touches), Utils.toArray(ev.changedTouches)); - var touchList = []; - - 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; - } + /** + * Remove an item from the corresponding DataSet + * @param {Item} item + */ + Group.prototype.removeFromDataSet = function(item) { + this.itemSet.removeItem(item.id); + }; - return { - center: Utils.getCenter(touches), - timeStamp: Date.now(), - target: ev.target, - touches: touches, - eventType: eventType, - pointerType: pointerType, - srcEvent: ev, + /** + * Reorder the items + */ + Group.prototype.order = function() { + var array = util.toArray(this.items); + this.orderedItems.byStart = array; + this.orderedItems.byEnd = this._constructByEndArray(array); - /** - * 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(); - }, + stack.orderByStart(this.orderedItems.byStart); + stack.orderByEnd(this.orderedItems.byEnd); + }; - /** - * stop bubbling the event up to its parents - */ - stopPropagation: function() { - this.srcEvent.stopPropagation(); - }, + /** + * 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 = []; - /** - * immediately stop gesture detection - * might be useful after a swipe was detected - * @return {*} - */ - stopDetect: function() { - return Detection.stopDetect(); - } - }; + for (var i = 0; i < array.length; i++) { + if (array[i] instanceof ItemRange) { + endArray.push(array[i]); } + } + return endArray; }; - /** - * @module hammer - * - * @class PointerEvent - * @static + * 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 */ - var PointerEvent = Hammer.PointerEvent = { - /** - * holds all pointers, by `identifier` - * @property pointers - * @type {Object} - */ - pointers: {}, - - /** - * 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; - }, + Group.prototype._updateVisibleItems = function(orderedItems, visibleItems, range) { + var initialPosByStart, + newVisibleItems = [], + i; - /** - * 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; - } - }, + // 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); + } + } - /** - * 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; - } + // 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]); + } - var pt = ev.pointerType, - types = {}; + // use visible search to find a visible ItemRange (only based on endTime) + var initialPosByEnd = util.binarySearch(orderedItems.byEnd, range, 'data','end'); - 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]; - }, + // 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;} + } + } - /** - * reset the stored pointers - * @method reset - */ - reset: function resetList() { - this.pointers = {}; + // 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 newVisibleItems; }; + /** - * @module hammer + * 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. * - * @class Detection - * @static + * @param {Item} item + * @param {Item[]} visibleItems + * @param {{start:number, end:number}} range + * @returns {boolean} + * @private */ - var Detection = Hammer.detection = { - // contains all registred Hammer.gestures in the correct order - gestures: [], - - // data of the current Hammer.gesture detection session - current: null, + 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; + } + }; - // the previous Hammer.gesture session data - // is a full clone of the previous gesture.current object - previous: null, + /** + * 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(); + } + }; - // when this becomes true, no gestures are fired - stopped: false, + module.exports = Group; - /** - * 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; - } - this.stopped = false; +/***/ }, +/* 24 */ +/***/ function(module, exports, __webpack_require__) { - // 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 - }; + 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); - this.detect(eventData); + + 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 }, - /** - * Hammer.gesture detection - * @method detect - * @param {Object} eventData - * @return {any} - */ - detect: function detect(eventData) { - if(!this.current || this.stopped) { - return; - } + onAdd: function (item, callback) { + callback(item); + }, + onUpdate: function (item, callback) { + callback(item); + }, + onMove: function (item, callback) { + callback(item); + }, + onRemove: function (item, callback) { + callback(item); + }, - // extend event data with calculations about scale, distance etc - eventData = this.extendEventData(eventData); + margin: { + item: { + horizontal: 10, + vertical: 10 + }, + axis: 20 + }, + padding: 5 + }; - // hammer instance and instance options - var inst = this.current.inst, - instOptions = inst.options; + // options is shared by this ItemSet and all its items + this.options = util.extend({}, this.defaultOptions); - // 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); + // options for getting items from the DataSet with the correct type + this.itemOptions = { + type: {start: 'Date', end: 'Date'} + }; - // store as previous event event - if(this.current) { - this.current.lastEvent = eventData; - } + this.conversion = { + toScreen: body.util.toScreen, + toTime: body.util.toTime + }; + this.dom = {}; + this.props = {}; + this.hammer = null; - if(eventData.eventType == EVENT_END) { - this.stopDetect(); - } + var me = this; + this.itemsData = null; // DataSet + this.groupsData = null; // DataSet - return eventData; + // 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); + } + }; - /** - * 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; + // 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); + } + }; - /** - * 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.items = {}; // object with an Item for every data item + this.groups = {}; // Group object for every group + this.groupIds = []; - 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.selection = []; // list with the ids of all selected nodes + this.stackDirty = true; // if true, all items will be restacked on next redraw - if(ev.eventType == EVENT_TOUCH || ev.eventType == EVENT_RELEASE) { - cur.futureCalcEvent = ev; - } + this.touchParams = {}; // stores properties while dragging + // create the HTML DOM - 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); + this._create(); - cur.lastCalcEvent = cur.futureCalcEvent || ev; - cur.futureCalcEvent = ev; - } + this.setOptions(options); + } - ev.velocityX = calcData.velocity.x; - ev.velocityY = calcData.velocity.y; - ev.interimAngle = calcData.angle; - ev.interimDirection = calcData.direction; - }, + ItemSet.prototype = new Component(); - /** - * 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; + // available item types will be registered here + ItemSet.types = { + box: ItemBox, + range: ItemRange, + point: ItemPoint + }; - // 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 - }); - }); - } + /** + * 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; - var deltaTime = ev.timeStamp - startEv.timeStamp, - deltaX = ev.center.clientX - startEv.center.clientX, - deltaY = ev.center.clientY - startEv.center.clientY; + // create background panel + var background = document.createElement('div'); + background.className = 'background'; + frame.appendChild(background); + this.dom.background = background; - this.getCalculatedData(ev, lastEv.center, deltaTime, deltaX, deltaY); + // create foreground panel + var foreground = document.createElement('div'); + foreground.className = 'foreground'; + frame.appendChild(foreground); + this.dom.foreground = foreground; - Utils.extend(ev, { - startEvent: startEv, + // create axis panel + var axis = document.createElement('div'); + axis.className = 'axis'; + this.dom.axis = axis; - deltaTime: deltaTime, - deltaX: deltaX, - deltaY: deltaY, + // create labelset + var labelSet = document.createElement('div'); + labelSet.className = 'labelset'; + this.dom.labelSet = labelSet; - 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) - }); + // create ungrouped Group + this._updateUngrouped(); - return ev; - }, + // 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 + }); - /** - * 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; - } + // 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)); - // extend Hammer default options with the Hammer.gesture options - Utils.extend(Hammer.defaults, options, true); + // single select (or unselect) when tapping an item + this.hammer.on('tap', this._onSelectItem.bind(this)); - // set its index - gesture.index = gesture.index || 1000; + // multi select when holding mouse/touch, or on ctrl+click + this.hammer.on('hold', this._onMultiSelectItem.bind(this)); - // add Hammer.gesture to the list - this.gestures.push(gesture); + // add item on doubletap + this.hammer.on('doubletap', this._onAddItem.bind(this)); - // 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; - }); + // attach to the DOM + this.show(); + }; - return this.gestures; + /** + * 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); + + 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); + } + } + } } - }; + 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); + } + } + + // 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); + + // force the itemSet to refresh: options like orientation and margins may be changed + this.markDirty(); + } + }; /** - * @module hammer + * Mark the ItemSet dirty so it will refresh everything with next redraw */ + ItemSet.prototype.markDirty = function() { + this.groupIds = []; + this.stackDirty = true; + }; /** - * 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} + * Destroy the ItemSet */ - Hammer.Instance = function(element, options) { - var self = this; + ItemSet.prototype.destroy = function() { + this.hide(); + this.setItems(null); + this.setGroups(null); - // setup HammerJS window events and register all gestures - // this also sets up the default options - setup(); + this.hammer = null; - /** - * @property element - * @type {HTMLElement} - */ - this.element = element; - - /** - * @property enabled - * @type {Boolean} - * @protected - */ - this.enabled = true; - - /** - * 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; - }); - - this.options = Utils.extend(Utils.extend({}, Hammer.defaults), options || {}); + this.body = null; + this.conversion = null; + }; - // 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); - } + /** + * 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); + } - /** - * 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); - } - }); + // remove the axis with dots + if (this.dom.axis.parentNode) { + this.dom.axis.parentNode.removeChild(this.dom.axis); + } - /** - * keep a list of user event handlers which needs to be removed when calling 'dispose' - * @property eventHandlers - * @type {Array} - */ - this.eventHandlers = []; + // remove the labelset containing all group labels + if (this.dom.labelSet.parentNode) { + this.dom.labelSet.parentNode.removeChild(this.dom.labelSet); + } }; - 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; - }, + /** + * 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); + } - /** - * unbind events to the instance - * @method off - * @chainable - * @param {String} gestures - * @param {Function} handler - */ - off: function offEvent(gestures, handler) { - var self = this; + // show axis with dots + if (!this.dom.axis.parentNode) { + this.body.dom.backgroundVertical.appendChild(this.dom.axis); + } - 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; - }, + // show labelset containing labels + if (!this.dom.labelSet.parentNode) { + this.body.dom.left.appendChild(this.dom.labelSet); + } + }; - /** - * trigger gesture event - * @method trigger - * @chainable - * @param {String} gesture - * @param {Object} [eventData] - */ - trigger: function triggerEvent(gesture, eventData) { - // optional - if(!eventData) { - eventData = {}; - } + /** + * 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; - // create DOM event - var event = Hammer.DOCUMENT.createEvent('Event'); - event.initEvent(gesture, true, true); - event.gesture = eventData; + if (ids) { + if (!Array.isArray(ids)) { + throw new TypeError('Array expected'); + } - // 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; - } + // 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(); + } - element.dispatchEvent(event); - return this; - }, + // 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(); + } + } + } + }; - /** - * enable of disable hammer.js detection - * @method enable - * @chainable - * @param {Boolean} state - */ - enable: function enable(state) { - this.enabled = state; - return this; - }, + /** + * Get the selected items by their id + * @return {Array} ids The ids of the selected items + */ + ItemSet.prototype.getSelection = function() { + return this.selection.concat([]); + }; - /** - * dispose this hammer instance - * @method dispose - * @return {Null} - */ - dispose: function dispose() { - var i, eh; + /** + * 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); - // undo all changes made by stop_browser_behavior - Utils.toggleBehavior(this.element, this.options.behavior, false); + var ids = []; + for (var groupId in this.groups) { + if (this.groups.hasOwnProperty(groupId)) { + var group = this.groups[groupId]; + var rawVisibleItems = group.visibleItems; - // unbind all custom event handlers - for(i = -1; (eh = this.eventHandlers[++i]);) { - Utils.off(this.element, eh.gesture, eh.handler); + // 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); } + } + } + } - this.eventHandlers = []; - - // unbind the start event listener - Event.off(this.element, EVENT_TYPES[EVENT_START], this.eventStartHandler); + return ids; + }; - return null; + /** + * 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; } + } }; - /** - * @module gestures + * Repaint the component + * @return {boolean} Returns true if the component is resized */ - /** - * 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 - */ - /** - * @event drag - * @param {Object} ev - */ - /** - * @event dragstart - * @param {Object} ev - */ - /** - * @event dragend - * @param {Object} ev - */ - /** - * @event drapleft - * @param {Object} ev - */ - /** - * @event dragright - * @param {Object} ev - */ - /** - * @event dragup - * @param {Object} ev - */ - /** - * @event dragdown - * @param {Object} ev - */ - - /** - * @param {String} name - */ - (function(name) { - var triggered = false; - - function dragGesture(ev, inst) { - var cur = Detection.current; + 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; - // max touches - if(inst.options.dragMaxTouches > 0 && - ev.touches.length > inst.options.dragMaxTouches) { - return; - } + // update class name + frame.className = 'itemset' + (editable ? ' editable' : ''); - switch(ev.eventType) { - case EVENT_START: - triggered = false; - break; + // reorder the groups (if needed) + resized = this._orderGroups() || resized; - 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; - } + // 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; - var startCenter = cur.startEvent.center; + // 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; - // 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; + // update frame height + frame.style.height = asSize(height); - // recalculate event data using new start point - ev = Detection.extendEventData(ev); - } - } + // calculate actual size and position + this.props.top = frame.offsetTop; + this.props.left = frame.offsetLeft; + this.props.width = frame.offsetWidth; + this.props.height = height; - // lock drag to axis? - if(cur.lastEvent.dragLockToAxis || - ( inst.options.dragLockToAxis && - inst.options.dragLockMinDistance <= ev.distance - )) { - ev.dragLockToAxis = true; - } + // 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'; - // 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; - } - } + // check if this component is resized + resized = this._isResized() || resized; - // first time, trigger dragstart event - if(!triggered) { - inst.trigger(name + 'start', ev); - triggered = true; - } + return resized; + }; - // trigger events - inst.trigger(name, ev); - inst.trigger(name + ev.direction, ev); + /** + * 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]; - var isVertical = Utils.isVertical(ev.direction); + return firstGroup || null; + }; - // block the browser events - if((inst.options.dragBlockVertical && isVertical) || - (inst.options.dragBlockHorizontal && !isVertical)) { - ev.preventDefault(); - } - 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_RELEASE: - if(triggered && ev.changedLength <= inst.options.dragMaxTouches) { - inst.trigger(name + 'end', ev); - 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; - case EVENT_END: - triggered = false; - break; + for (var itemId in this.items) { + if (this.items.hasOwnProperty(itemId)) { + ungrouped.add(this.items[itemId]); } - } + } - 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, + ungrouped.show(); + } + } + }; - /** - * 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, + /** + * Get the element for the labelset + * @return {HTMLElement} labelSet + */ + ItemSet.prototype.getLabelSet = function() { + return this.dom.labelSet; + }; - /** - * set 0 for unlimited, but this can conflict with transform - * @property dragMaxTouches - * @type {Number} - * @default 1 - */ - dragMaxTouches: 1, + /** + * Set items + * @param {vis.DataSet | null} items + */ + ItemSet.prototype.setItems = function(items) { + var me = this, + ids, + oldItemsData = this.itemsData; - /** - * 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, + // 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'); + } - /** - * same as `dragBlockHorizontal`, but for vertical movement - * @property dragBlockVertical - * @type {Boolean} - * @default false - */ - dragBlockVertical: false, + if (oldItemsData) { + // unsubscribe from old dataset + util.forEach(this.itemListeners, function (callback, event) { + oldItemsData.off(event, callback); + }); - /** - * 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, + // remove all drawn items + ids = oldItemsData.getIds(); + this._onRemove(ids); + } - /** - * 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'); + if (this.itemsData) { + // subscribe to new dataset + var id = this.id; + util.forEach(this.itemListeners, function (callback, event) { + me.itemsData.on(event, callback, id); + }); - /** - * @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); - } + // add all new items + ids = this.itemsData.getIds(); + this._onAdd(ids); + + // update the group holding all ungrouped items + this._updateUngrouped(); + } }; /** - * @module gestures - */ - /** - * Touch stays at the same place for x time - * - * @class Hold - * @static - */ - /** - * @event hold - * @param {Object} ev + * Get the current items + * @returns {vis.DataSet | null} */ + ItemSet.prototype.getItems = function() { + return this.itemsData; + }; /** - * @param {String} name + * Set groups + * @param {vis.DataSet} groups */ - (function(name) { - var timer; + ItemSet.prototype.setGroups = function(groups) { + var me = this, + ids; - function holdGesture(ev, inst) { - var options = inst.options, - current = Detection.current; + // unsubscribe from current dataset + if (this.groupsData) { + util.forEach(this.groupListeners, function (callback, event) { + me.groupsData.unsubscribe(event, callback); + }); - switch(ev.eventType) { - case EVENT_START: - clearTimeout(timer); + // remove all drawn groups + ids = this.groupsData.getIds(); + this.groupsData = null; + this._onRemoveGroups(ids); // note: this will cause a redraw + } - // set the gesture so we can check in the timeout if it still is - current.name = name; + // 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'); + } - // 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.groupsData) { + // subscribe to new dataset + var id = this.id; + util.forEach(this.groupListeners, function (callback, event) { + me.groupsData.on(event, callback, id); + }); - case EVENT_MOVE: - if(ev.distance > options.holdThreshold) { - clearTimeout(timer); - } - break; + // draw all ms + ids = this.groupsData.getIds(); + this._onAddGroups(ids); + } - case EVENT_RELEASE: - clearTimeout(timer); - break; - } - } + // update the group holding all ungrouped items + this._updateUngrouped(); - Hammer.gestures.Hold = { - name: name, - index: 10, - defaults: { - /** - * @property holdTimeout - * @type {Number} - * @default 500 - */ - holdTimeout: 500, + // update the order of all items in each group + this._order(); - /** - * movement allowed while holding - * @property holdThreshold - * @type {Number} - * @default 2 - */ - holdThreshold: 2 - }, - handler: holdGesture - }; - })('hold'); + this.body.emitter.emit('change'); + }; /** - * @module gestures - */ - /** - * when a touch is being released from the page - * - * @class Release - * @static - */ - /** - * @event release - * @param {Object} ev + * Get the current groups + * @returns {vis.DataSet | null} groups */ - Hammer.gestures.Release = { - name: 'release', - index: Infinity, - handler: function releaseGesture(ev, inst) { - if(ev.eventType == EVENT_RELEASE) { - inst.trigger(this.name, ev); - } - } + ItemSet.prototype.getGroups = function() { + return this.groupsData; }; /** - * @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 + * 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(); + + 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); + } + }); + } + }; + /** - * @event swipe - * @param {Object} ev + * Handle updated items + * @param {Number[]} ids + * @protected */ - /** - * @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, - - /** - * @property swipeMaxTouches - * @type {Number} - * @default 1 - */ - swipeMaxTouches: 1, - - /** - * horizontal swipe velocity - * @property swipeVelocityX - * @type {Number} - * @default 0.6 - */ - swipeVelocityX: 0.6, + ItemSet.prototype._onUpdate = function(ids) { + var me = this; - /** - * vertical swipe velocity - * @property swipeVelocityY - * @type {Number} - * @default 0.6 - */ - swipeVelocityY: 0.6 - }, + 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'); - handler: function swipeGesture(ev, inst) { - if(ev.eventType == EVENT_RELEASE) { - var touches = ev.touches.length, - options = inst.options; + var constructor = ItemSet.types[type]; - // max touches - if(touches < options.swipeMinTouches || - touches > options.swipeMaxTouches) { - return; - } + 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); + } + } - // 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); - } - } + 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 + '"'); + } } + }); + + this._order(); + this.stackDirty = true; // force re-stacking of all items next redraw + this.body.emitter.emit('change'); }; /** - * @module gestures + * Handle added items + * @param {Number[]} ids + * @protected */ + ItemSet.prototype._onAdd = ItemSet.prototype._onUpdate; + /** - * Single tap and a double tap on a place - * - * @class Tap - * @static + * 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); + } + }); + + if (count) { + // update order + this._order(); + this.stackDirty = true; // force re-stacking of all items next redraw + this.body.emitter.emit('change'); + } + }; + /** - * @event tap - * @param {Object} ev + * 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(); + }); + }; + /** - * @event doubletap - * @param {Object} ev + * Handle updated groups + * @param {Number[]} ids + * @private */ + ItemSet.prototype._onUpdateGroups = function(ids) { + this._onAddGroups(ids); + }; /** - * @param {String} name + * Handle changed groups + * @param {Number[]} ids + * @private */ - (function(name) { - var hasMoved = false; - - function tapGesture(ev, inst) { - var options = inst.options, - current = Detection.current, - prev = Detection.previous, - sincePrev, - didDoubleTap; + ItemSet.prototype._onAddGroups = function(ids) { + var me = this; - switch(ev.eventType) { - case EVENT_START: - hasMoved = false; - break; + ids.forEach(function (id) { + var groupData = me.groupsData.get(id); + var group = me.groups[id]; - case EVENT_MOVE: - hasMoved = hasMoved || (ev.distance > options.tapMaxDistance); - break; + if (!group) { + // check for reserved ids + if (id == UNGROUPED) { + throw new Error('Illegal group id. ' + id + ' is a reserved id.'); + } - 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; + var groupOptions = Object.create(me.options); + util.extend(groupOptions, { + height: null + }); - // check if double tap - if(prev && prev.name == name && - (sincePrev && sincePrev < options.doubleTapInterval) && - ev.distance < options.doubleTapDistance) { - inst.trigger('doubletap', ev); - didDoubleTap = true; - } + group = new Group(id, groupData, me); + me.groups[id] = group; - // do a single tap - if(!didDoubleTap || options.tapAlways) { - current.name = name; - inst.trigger(current.name, ev); - } - } - break; + // 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); } + }); - 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, + this.body.emitter.emit('change'); + }; - /** - * max distance of movement of a tap, this is for the slow tappers - * @property tapMaxDistance - * @type {Number} - * @default 10 - */ - tapMaxDistance: 10, + /** + * Handle removed groups + * @param {Number[]} ids + * @private + */ + ItemSet.prototype._onRemoveGroups = function(ids) { + var groups = this.groups; + ids.forEach(function (id) { + var group = groups[id]; - /** - * always trigger the `tap` event, even while double-tapping - * @property tapAlways - * @type {Boolean} - * @default true - */ - tapAlways: true, + if (group) { + group.hide(); + delete groups[id]; + } + }); - /** - * max distance between two taps - * @property doubleTapDistance - * @type {Number} - * @default 20 - */ - doubleTapDistance: 20, + this.markDirty(); - /** - * max time between two taps - * @property doubleTapInterval - * @type {Number} - * @default 300 - */ - doubleTapInterval: 300 - } - }; - })('tap'); + this.body.emitter.emit('change'); + }; /** - * @module gestures - */ - /** - * when a touch is being touched at the page - * - * @class Touch - * @static - */ - /** - * @event touch - * @param {Object} ev + * Reorder the groups if needed + * @return {boolean} changed + * @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._orderGroups = function () { + if (this.groupsData) { + // reorder the groups + var groupIds = this.groupsData.getIds({ + order: this.options.groupOrder + }); - /** - * 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; - } + 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(); + }); - if(inst.options.preventDefault) { - ev.preventDefault(); - } + // show the groups again, attach them to the DOM in correct order + groupIds.forEach(function (groupId) { + groups[groupId].show(); + }); - if(ev.eventType == EVENT_TOUCH) { - inst.trigger('touch', ev); - } + this.groupIds = groupIds; } + + return changed; + } + else { + return false; + } }; /** - * @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 + * 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); + }; + /** - * @event transformend - * @param {Object} ev + * Update an existing item + * @param {Item} item + * @param {Object} itemData + * @private */ + ItemSet.prototype._updateItem = function(item, itemData) { + var oldGroupId = item.data.group; + + item.data = itemData; + if (item.displayed) { + item.redraw(); + } + + // update group + if (oldGroupId != item.data.group) { + var oldGroup = this.groups[oldGroupId]; + if (oldGroup) oldGroup.remove(item); + + var groupId = this.groupsData ? item.data.group : UNGROUPED; + var group = this.groups[groupId]; + if (group) group.add(item); + } + }; + /** - * @event pinchin - * @param {Object} ev + * 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 */ + 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); + + // remove from group + var groupId = this.groupsData ? item.data.group : UNGROUPED; + var group = this.groups[groupId]; + if (group) group.remove(item); + }; + /** - * @event pinchout - * @param {Object} ev + * 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 = []; + + for (var i = 0; i < array.length; i++) { + if (array[i] instanceof ItemRange) { + endArray.push(array[i]); + } + } + return endArray; + }; + /** - * @event rotate - * @param {Object} ev + * 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); + }; /** - * @param {String} name + * Start dragging the selected events + * @param {Event} event + * @private */ - (function(name) { - var triggered = false; - - function transformGesture(ev, inst) { - switch(ev.eventType) { - case EVENT_START: - triggered = false; - break; + ItemSet.prototype._onDragStart = function (event) { + if (!this.options.editable.updateTime && !this.options.editable.updateGroup) { + return; + } - case EVENT_MOVE: - // at least multitouch - if(ev.touches.length < 2) { - return; - } + var item = this.touchParams.item || null, + me = this, + props; - var scaleThreshold = Math.abs(1 - ev.scale); - var rotationThreshold = Math.abs(ev.rotation); + if (item && item.selected) { + var dragLeftItem = event.target.dragLeftItem; + var dragRightItem = event.target.dragRightItem; - // 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 (dragLeftItem) { + props = { + item: dragLeftItem + }; - // we are transforming! - Detection.current.name = name; + 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; + } - // first time, trigger dragstart event - if(!triggered) { - inst.trigger(name + 'start', ev); - triggered = true; - } - - inst.trigger(name, ev); // basic transform event - - // trigger rotate event - if(rotationThreshold > inst.options.transformMinRotation) { - inst.trigger('rotate', ev); - } + this.touchParams.itemProps = [props]; + } + else if (dragRightItem) { + props = { + item: dragRightItem + }; - // trigger pinch event - if(scaleThreshold > inst.options.transformMinScale) { - inst.trigger('pinch', ev); - inst.trigger('pinch' + (ev.scale < 1 ? 'in' : 'out'), ev); - } - break; + 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; + } - case EVENT_RELEASE: - if(triggered && ev.changedLength < 2) { - inst.trigger(name + 'end', ev); - triggered = false; - } - break; - } + this.touchParams.itemProps = [props]; } + else { + this.touchParams.itemProps = this.getSelection().map(function (id) { + var item = me.items[id]; + var props = { + item: item + }; - 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, + 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; + } - /** - * rotation in degrees - * @property transformMinRotation - * @type {Number} - * @default 1 - */ - transformMinRotation: 1 - }, + return props; + }); + } - handler: transformGesture - }; - })('transform'); + event.stopPropagation(); + } + }; /** - * @module hammer + * 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; - // 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; - } + // 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; + } - })(window); + if ('end' in props) { + var end = new Date(props.end + offset); + props.item.data.end = snap ? snap(end) : end; + } -/***/ }, -/* 20 */ -/***/ function(module, exports, __webpack_require__) { + if ('group' in props) { + // drag from one group to another + var group = ItemSet.groupFromTarget(event); + if (group && group.groupId != props.item.data.group) { + var oldGroup = props.item.parent; + oldGroup.remove(props.item); + oldGroup.order(); + group.add(props.item); + group.order(); - var util = __webpack_require__(1); - var hammerUtil = __webpack_require__(21); - var moment = __webpack_require__(2); - var Component = __webpack_require__(22); + props.item.data.group = group.groupId; + } + } + }); - /** - * @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 - */ - 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 + // TODO: implement onMoving handler - this.body = body; + this.stackDirty = true; // force re-stacking of all items next redraw + this.body.emitter.emit('change'); - // 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); + event.stopPropagation(); + } + }; - this.props = { - touch: {} - }; + /** + * End of dragging selected items + * @param {Event} event + * @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(); - // 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.touchParams.itemProps.forEach(function (props) { + var id = props.item.id, + itemData = me.itemsData.get(id, me.itemOptions); - // ignore dragging when holding - this.body.emitter.on('hold', this._onHold.bind(this)); + 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; + } - // mouse wheel for zooming - this.body.emitter.on('mousewheel', this._onMouseWheel.bind(this)); - this.body.emitter.on('DOMMouseScroll', this._onMouseWheel.bind(this)); // For FF + // 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; - // pinch to zoom - this.body.emitter.on('touch', this._onTouch.bind(this)); - this.body.emitter.on('pinch', this._onPinch.bind(this)); + me.stackDirty = true; // force re-stacking of all items next redraw + me.body.emitter.emit('change'); + } + }); + } + }); + this.touchParams.itemProps = null; - this.setOptions(options); - } + // apply the changes to the data (if there are changes) + if (changes.length) { + dataset.update(changes); + } - Range.prototype = new Component(); + event.stopPropagation(); + } + }; /** - * 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 + * Handle selecting/deselecting an item when tapping it + * @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); + ItemSet.prototype._onSelectItem = function (event) { + if (!this.options.selectable) return; - if ('start' in options || 'end' in options) { - // apply a new range. both start and end are optional - this.setRange(options.start, options.end); - } + 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; } - }; - /** - * Test whether direction has a valid value - * @param {String} direction 'horizontal' or 'vertical' - */ - function validateDirection (direction) { - if (direction != 'horizontal' && direction != 'vertical') { - throw new TypeError('Unknown direction "' + direction + '". ' + - 'Choose "horizontal" or "vertical".'); - } - } + var oldSelection = this.getSelection(); - /** - * 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 = 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() + }); } + + event.stopPropagation(); }; /** - * 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 + * Handle creation and updates of an item on double tap + * @param event * @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; - - // 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 + '"'); - } + ItemSet.prototype._onAddItem = function (event) { + if (!this.options.selectable) return; + if (!this.options.editable.add) return; - // prevent start < end - if (newEnd < newStart) { - newEnd = newStart; - } + var me = this, + snap = this.body.util.snap || null, + item = ItemSet.itemFromTarget(event); - // prevent start < min - if (min !== null) { - if (newStart < min) { - diff = (min - newStart); - newStart += diff; - newEnd += diff; + if (item) { + // update item - // prevent end > max - if (max != null) { - if (newEnd > max) { - newEnd = max; - } + // 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' + }; - // prevent end > max - if (max !== null) { - if (newEnd > max) { - diff = (newEnd - max); - newStart -= diff; - newEnd -= diff; - - // prevent start < min - if (min != null) { - if (newStart < min) { - newStart = min; - } - } + // 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; } - } - // prevent (end-start) < zoomMin - if (this.options.zoomMin !== null) { - var zoomMin = parseFloat(this.options.zoomMin); - if (zoomMin < 0) { - zoomMin = 0; + newItem[this.itemsData.fieldId] = util.randomUUID(); + + var group = ItemSet.groupFromTarget(event); + if (group) { + newItem.group = group.groupId; } - 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; + + // 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? } - } + }); } + }; - // prevent (end-start) > zoomMax - if (this.options.zoomMax !== null) { - var zoomMax = parseFloat(this.options.zoomMax); - if (zoomMax < 0) { - zoomMax = 0; + /** + * Handle selecting/deselecting multiple items when holding an item + * @param {Event} 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); } - 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; - } + else { + // item is already selected -> deselect it + selection.splice(index, 1); } - } - - var changed = (this.start != newStart || this.end != newEnd); + this.setSelection(selection); - this.start = newStart; - this.end = newEnd; + this.body.emitter.emit('select', { + items: this.getSelection() + }); - return changed; + event.stopPropagation(); + } }; /** - * Retrieve the current range. - * @return {Object} An object with start and end properties + * 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.getRange = function() { - return { - start: this.start, - end: this.end - }; + ItemSet.itemFromTarget = function(event) { + var target = event.target; + while (target) { + if (target.hasOwnProperty('timeline-item')) { + return target['timeline-item']; + } + target = target.parentNode; + } + + return null; }; /** - * Calculate the conversion offset and scale for current range, based on - * the provided width - * @param {Number} width - * @returns {{offset: number, scale: number}} conversion + * 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.conversion = function (width) { - return Range.conversion(this.start, this.end, width); + ItemSet.groupFromTarget = function(event) { + var target = event.target; + while (target) { + if (target.hasOwnProperty('timeline-group')) { + return target['timeline-group']; + } + target = target.parentNode; + } + + return null; }; /** - * 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 + * 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.conversion = function (start, end, width) { - if (width != 0 && (end - start != 0)) { - return { - offset: start, - scale: width / (end - start) + ItemSet.itemSetFromTarget = function(event) { + var target = event.target; + while (target) { + if (target.hasOwnProperty('timeline-itemset')) { + return target['timeline-itemset']; } + target = target.parentNode; } - else { - return { - offset: 0, - scale: 1 - }; - } + + return null; }; - /** - * Start dragging horizontally or vertically - * @param {Event} event - * @private - */ - Range.prototype._onDragStart = function(event) { - // only allow dragging when configured as movable - if (!this.options.moveable) return; + module.exports = ItemSet; - // 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; +/***/ }, +/* 25 */ +/***/ function(module, exports, __webpack_require__) { - if (this.body.dom.root) { - this.body.dom.root.style.cursor = 'move'; - } - }; + var util = __webpack_require__(1); + var DOMutil = __webpack_require__(2); + var Component = __webpack_require__(18); /** - * Perform dragging operation - * @param {Event} event - * @private + * Legend for Graph2d */ - 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) - }); - }; + 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); - /** - * Stop dragging operation - * @param {event} event - * @private - */ - Range.prototype._onDragEnd = function (event) { - // only allow dragging when configured as movable - if (!this.options.moveable) return; + this.svgElements = {}; + this.dom = {}; + this.groups = {}; + this.amountOfGroups = 0; + this._create(); - // 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.setOptions(options); + } - if (this.body.dom.root) { - this.body.dom.root.style.cursor = 'auto'; - } + Legend.prototype = new Component(); - // fire a rangechanged event - this.body.emitter.emit('rangechanged', { - start: new Date(this.start), - end: new Date(this.end) - }); + + Legend.prototype.addGroup = function(label, graphOptions) { + if (!this.groups.hasOwnProperty(label)) { + this.groups[label] = graphOptions; + } + this.amountOfGroups += 1; }; - /** - * Event handler for mouse wheel event, used to zoom - * Code from http://adomas.org/javascript-mouse-wheel/ - * @param {Event} event - * @private - */ - Range.prototype._onMouseWheel = function(event) { - // only allow zooming when configured as zoomable and moveable - if (!(this.options.zoomable && this.options.moveable)) return; + Legend.prototype.updateGroup = function(label, graphOptions) { + this.groups[label] = graphOptions; + }; - // 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; + Legend.prototype.removeGroup = function(label) { + if (this.groups.hasOwnProperty(label)) { + delete this.groups[label]; + this.amountOfGroups -= 1; } + }; - // 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 - - // 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)) ; - } + 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"; - // 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.dom.textArea = document.createElement('div'); + this.dom.textArea.className = 'legendText'; + this.dom.textArea.style.position = "relative"; + this.dom.textArea.style.top = "0px"; - this.zoom(scale, pointerDate); - } + 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'; - // Prevent default actions caused by mouse wheel - // (else the page and timeline both zoom and scroll) - event.preventDefault(); + this.dom.frame.appendChild(this.svg); + this.dom.frame.appendChild(this.dom.textArea); }; /** - * Start of a touch gesture - * @private + * Hide the component from the DOM */ - 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; + Legend.prototype.hide = function() { + // remove the frame containing the items + if (this.dom.frame.parentNode) { + this.dom.frame.parentNode.removeChild(this.dom.frame); + } }; /** - * On start of a hold gesture - * @private + * Show the component in the DOM (when not already visible). + * @return {Boolean} changed */ - Range.prototype._onHold = function () { - this.props.touch.allowDragging = false; + Legend.prototype.show = function() { + // show frame containing the items + if (!this.dom.frame.parentNode) { + this.body.dom.center.appendChild(this.dom.frame); + } }; - /** - * 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; + Legend.prototype.setOptions = function(options) { + var fields = ['enabled','orientation','icons','left','right']; + util.selectiveDeepExtend(fields, this.options, options); + }; - this.props.touch.allowDragging = false; + Legend.prototype.redraw = function() { + if (this.options[this.side].visible == false || this.amountOfGroups == 0 || this.options.enabled == false) { + 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 (event.gesture.touches.length > 1) { - if (!this.props.touch.center) { - this.props.touch.center = getPointer(event.gesture.center, this.body.dom.center); + 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 = ''; } - 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); + 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(); + } - // apply new range - this.setRange(newStart, newEnd); + var content = ''; + for (var groupId in this.groups) { + if (this.groups.hasOwnProperty(groupId)) { + content += this.groups[groupId].content + '
'; + } + } + this.dom.textArea.innerHTML = content; + this.dom.textArea.style.lineHeight = ((0.75 * this.options.iconSize) + this.options.iconSpacing) + 'px'; } }; - /** - * 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; + 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; - validateDirection(direction); + this.svg.style.width = iconWidth + 5 + iconOffset + 'px'; - 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; + for (var groupId in this.groups) { + if (this.groups.hasOwnProperty(groupId)) { + this.groups[groupId].drawIcon(x, y, this.svgElements, this.svg, iconWidth, iconHeight); + y += iconHeight + this.options.iconSpacing; + } + } + + DOMutil.cleanupElements(this.svgElements); } }; - /** - * 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) - }; - } + module.exports = Legend; - /** - * 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; - } - // calculate new start and end - var newStart = center + (this.start - center) * scale; - var newEnd = center + (this.end - center) * scale; +/***/ }, +/* 26 */ +/***/ function(module, exports, __webpack_require__) { - this.setRange(newStart, newEnd); - }; + var util = __webpack_require__(1); + 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 /** - * 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 + * This is the constructor of the LineGraph. It requires a Timeline body and options. + * + * @param body + * @param options + * @constructor */ - 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; + function LineGraph(body, options) { + this.id = util.randomUUID(); + this.body = body; - // TODO: reckon with min and max range + 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, + 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 + } + } + }; - this.start = newStart; - this.end = newEnd; - }; + // 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 = {}; - /** - * Move the range to a new center point - * @param {Number} moveTo New center point of the range - */ - Range.prototype.moveTo = function(moveTo) { - var center = (this.start + this.end) / 2; + var me = this; + this.itemsData = null; // DataSet + this.groupsData = null; // DataSet - var diff = center - moveTo; + // 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); + } + }; - // calculate new start and end - var newStart = this.start - diff; - var newEnd = this.end - diff; + // 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.setRange(newStart, newEnd); - }; + 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 - module.exports = Range; + 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); + }); -/***/ }, -/* 21 */ -/***/ function(module, exports, __webpack_require__) { + // create the HTML DOM + this._create(); + this.body.emitter.emit("change"); + } - var Hammer = __webpack_require__(18); + LineGraph.prototype = new Component(); /** - * Fake a hammer.js gesture. Event can be a ScrollEvent or MouseMoveEvent - * @param {Element} element - * @param {Event} event + * Create the HTML DOM for the ItemSet */ - exports.fakeGesture = function(element, event) { - var eventType = null; + LineGraph.prototype._create = function(){ + var frame = document.createElement('div'); + frame.className = 'LineGraph'; + this.dom.frame = frame; - // 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; - } - - return gesture; - }; - - -/***/ }, -/* 22 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * 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); - } - }; - - /** - * Repaint the component - * @return {boolean} Returns true if the component is resized - */ - Component.prototype.redraw = function() { - // should be implemented by the component - return false; - }; - - /** - * Destroy the component. Cleanup DOM and event listeners - */ - Component.prototype.destroy = function() { - // should be implemented by the component - }; - - /** - * Test whether the component is resized since the last time _isResized() was - * called. - * @return {Boolean} Returns true if the component is resized - * @protected - */ - Component.prototype._isResized = function() { - var resized = (this.props._previousWidth !== this.props.width || - this.props._previousHeight !== this.props.height); - - this.props._previousWidth = this.props.width; - this.props._previousHeight = this.props.height; - - return resized; - }; - - module.exports = Component; - - -/***/ }, -/* 23 */ -/***/ 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); - - /** - * 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 = {}; + // 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); - 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 = {}; + // data axis + this.options.dataAxis.orientation = 'left'; + this.yAxisLeft = new DataAxis(this.body, this.options.dataAxis, this.svg); - 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.options.dataAxis.orientation = 'right'; + this.yAxisRight = new DataAxis(this.body, this.options.dataAxis, this.svg); + delete this.options.dataAxis.orientation; - // 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 + // legends + this.legendLeft = new Legend(this.body, this.options.legend, 'left'); + this.legendRight = new Legend(this.body, this.options.legend, 'right'); - // attach the root panel to the provided container - if (!container) throw new Error('No container provided'); - container.appendChild(this.dom.root); + this.show(); }; /** - * Destroy the Core, clean up all DOM elements and event listeners. + * set the options of the LineGraph. the mergeOptions is used for subObjects that have an enabled element. + * @param options */ - Core.prototype.destroy = function () { - // unbind datasets - this.clear(); + 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'); - // remove all event listeners - this.off(); + 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; + } + } + } + } - // stop checking for changed size - this._stopAutoResize(); + if (this.yAxisLeft) { + if (options.dataAxis !== undefined) { + this.yAxisLeft.setOptions(this.options.dataAxis); + this.yAxisRight.setOptions(this.options.dataAxis); + } + } - // remove from DOM - if (this.dom.root.parentNode) { - this.dom.root.parentNode.removeChild(this.dom.root); - } - this.dom = null; + if (this.legendLeft) { + if (options.legend !== undefined) { + this.legendLeft.setOptions(this.options.legend); + this.legendRight.setOptions(this.options.legend); + } + } - // cleanup hammer touch events - for (var event in this.listeners) { - if (this.listeners.hasOwnProperty(event)) { - delete this.listeners[event]; + if (this.groups.hasOwnProperty(UNGROUPED)) { + this.groups[UNGROUPED].setOptions(options); } } - this.listeners = null; - this.hammer = null; - - // give all components the opportunity to cleanup - this.components.forEach(function (component) { - component.destroy(); - }); - - this.body = null; + if (this.dom.frame) { + this._updateGraph(); + } }; - /** - * Set a custom time bar - * @param {Date} time + * Hide the component from the DOM */ - Core.prototype.setCustomTime = function (time) { - 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); } - - this.customTime.setCustomTime(time); }; /** - * Retrieve the current custom time. - * @return {Date} customTime + * Show the component in the DOM (when not already visible). + * @return {Boolean} changed */ - Core.prototype.getCustomTime = function() { - if (!this.customTime) { - throw new Error('Cannot get custom time: Custom time bar is not enabled'); + LineGraph.prototype.show = function() { + // show frame containing the items + if (!this.dom.frame.parentNode) { + this.body.dom.center.appendChild(this.dom.frame); } - - return this.customTime.getCustomTime(); }; /** - * Get the id's of the currently visible items. - * @returns {Array} The ids of the visible items + * Set items + * @param {vis.DataSet | null} items */ - Core.prototype.getVisibleItems = function() { - return this.itemSet && this.itemSet.getVisibleItems() || []; - }; - - + LineGraph.prototype.setItems = function(items) { + var me = this, + ids, + oldItemsData = this.itemsData; - /** - * 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); + // replace the dataset + if (!items) { + this.itemsData = null; } - - // clear groups - if (!what || what.groups) { - this.setGroups(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 options of timeline and of each of the components - if (!what || what.options) { - this.components.forEach(function (component) { - component.setOptions(component.defaultOptions); + if (oldItemsData) { + // unsubscribe from old dataset + util.forEach(this.itemListeners, function (callback, event) { + oldItemsData.off(event, callback); }); - this.setOptions(this.defaultOptions); // this will also do a redraw + // remove all drawn items + ids = oldItemsData.getIds(); + this._onRemove(ids); } - }; - - /** - * 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); - } + if (this.itemsData) { + // subscribe to new dataset + var id = this.id; + util.forEach(this.itemListeners, function (callback, event) { + me.itemsData.on(event, callback, id); + }); - // skip range set if there is no start and end date - if (start === null && end === null) { - return; + // add all new items + ids = this.itemsData.getIds(); + this._onAdd(ids); } - - this.range.setRange(start, end); + this._updateUngrouped(); + this._updateGraph(); + this.redraw(); }; /** - * 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 + * Set groups + * @param {vis.DataSet} groups */ - Core.prototype.getItemRange = function() { - // calculate min from start filed - var dataset = this.itemsData.getDataSet(), - min = null, - max = null; - - 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 + LineGraph.prototype.setGroups = function(groups) { + var me = this, + ids; - // 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()); - } - } - } + // unsubscribe from current dataset + if (this.groupsData) { + util.forEach(this.groupListeners, function (callback, event) { + me.groupsData.unsubscribe(event, callback); + }); - return { - min: (min != null) ? new Date(min) : null, - max: (max != null) ? new Date(max) : null - }; - }; + // remove all drawn groups + ids = this.groupsData.getIds(); + this.groupsData = null; + this._onRemoveGroups(ids); // note: this will cause a 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. - * - * @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); + // replace the dataset + if (!groups) { + this.groupsData = null; + } + else if (groups instanceof DataSet || groups instanceof DataView) { + this.groupsData = groups; } else { - this.range.setRange(start, end); + throw new TypeError('Data must be an instance of DataSet or DataView'); } - }; - - /** - * 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) - }; - }; - /** - * 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 (this.groupsData) { + // subscribe to new dataset + var id = this.id; + util.forEach(this.groupListeners, function (callback, event) { + me.groupsData.on(event, callback, id); + }); - 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(); + // draw all ms + ids = this.groupsData.getIds(); + this._onAddGroups(ids); } + this._onUpdate(); }; - // 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); - }; - /** - * 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); + 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]); + } - /** - * 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; + this._updateGraph(); + this.redraw(); }; + LineGraph.prototype._onAddGroups = function (groupIds) {this._onUpdateGroups(groupIds);}; - - /** - * 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; + 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(); }; - /** - * Initialize watching when option autoResize is true + * update a group object + * + * @param group + * @param groupId * @private */ - Core.prototype._initAutoResize = function () { - if (this.options.autoResize == true) { - this._startAutoResize(); + 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._stopAutoResize(); + 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(); }; - /** - * 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; - - this._stopAutoResize(); + LineGraph.prototype._updateAllGroupData = function () { + if (this.itemsData != null) { + // ~450 ms @ 500k - this._onResize = function() { - if (me.options.autoResize != true) { - // stop watching when the option autoResize is changed to false - me._stopAutoResize(); - return; + var groupsContent = {}; + for (var groupId in this.groups) { + if (this.groups.hasOwnProperty(groupId)) { + groupsContent[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; - - me.emit('change'); + 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); } } - }; - - // add event listener to window resize - util.addEventListener(window, 'resize', this._onResize); - - this.watchTimer = setInterval(this._onResize, 1000); - }; - - /** - * Stop watching for a resize of the frame. - * @private - */ - Core.prototype._stopAutoResize = function () { - if (this.watchTimer) { - clearInterval(this.watchTimer); - this.watchTimer = undefined; + for (var groupId in this.groups) { + if (this.groups.hasOwnProperty(groupId)) { + this.groups[groupId].setItems(groupsContent[groupId]); + } + } + // // ~4500ms @ 500k + // for (var groupId in this.groups) { + // if (this.groups.hasOwnProperty(groupId)) { + // this.groups[groupId].setItems(this.itemsData.get({filter: + // function (item) { + // return (item.group == groupId); + // }, type:{x:"Date"}} + // )); + // } + // } } - - // remove event listener on window.resize - util.removeEventListener(window, 'resize', this._onResize); - this._onResize = null; }; /** - * Start moving the timeline vertically - * @param {Event} event - * @private + * 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._onTouch = function (event) { - this.touch.allowDragging = true; - }; + 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; + } + } + } + } - /** - * Start moving the timeline vertically - * @param {Event} event - * @private - */ - Core.prototype._onPinch = function (event) { - this.touch.allowDragging = false; - }; + // 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); + } + else { + delete this.groups[UNGROUPED]; + this.legendLeft.removeGroup(UNGROUPED); + this.legendRight.removeGroup(UNGROUPED); + this.yAxisLeft.removeGroup(UNGROUPED); + this.yAxisRight.removeGroup(UNGROUPED); + } - /** - * Start moving the timeline vertically - * @param {Event} event - * @private - */ - Core.prototype._onDragStart = function (event) { - this.touch.initialScrollTop = this.props.scrollTop; + this.legendLeft.redraw(); + this.legendRight.redraw(); }; - /** - * 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; - - 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 - } - }; /** - * Apply a scrollTop - * @param {Number} scrollTop - * @returns {Number} scrollTop Returns the applied scrollTop - * @private + * Redraw the component, mandatory function + * @return {boolean} Returns true if the component is resized */ - Core.prototype._setScrollTop = function (scrollTop) { - this.props.scrollTop = scrollTop; - this._updateScrollTop(); - return this.props.scrollTop; - }; + LineGraph.prototype.redraw = function() { + var resized = false; - /** - * Update the current scrollTop when the height of the containers has been changed - * @returns {Number} scrollTop Returns the applied scrollTop - * @private - */ - 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; + 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; + + // 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); + } + if (zoomed == true) { + this._updateGraph(); } - // 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.legendLeft.redraw(); + this.legendRight.redraw(); - return this.props.scrollTop; + return resized; }; /** - * Get the current scrollTop - * @returns {number} scrollTop - * @private + * Update and redraw the graph. + * */ - Core.prototype._getScrollTop = function () { - return this.props.scrollTop; - }; - - module.exports = Core; - + LineGraph.prototype._updateGraph = function () { + // reset the svg elements + DOMutil.prepareElements(this.svgElements); + // // very slow... + // groupData = group.itemsData.get({filter: + // function (item) { + // return (item.x > minDate && item.x < maxDate); + // }} + // ); -/***/ }, -/* 24 */ -/***/ function(module, exports, __webpack_require__) { - var util = __webpack_require__(1); - var Component = __webpack_require__(22); - var TimeStep = __webpack_require__(25); + if (this.width != 0 && this.itemsData != null) { + var group, groupData, preprocessedGroup, i; + var preprocessedGroupData = []; + var processedGroupData = []; + var groupRanges = []; + var changeCalled = false; - /** - * 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: [] + // getting group Ids + var groupIds = []; + for (var groupId in this.groups) { + if (this.groups.hasOwnProperty(groupId)) { + groupIds.push(groupId); + } } - }; - 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; + // 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); - // create the HTML DOM - this._create(); + // 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]]; + 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 + preprocessedGroup = this._preprocessData(groupData, group); + groupRanges.push({min: preprocessedGroup.min, max: preprocessedGroup.max}); + preprocessedGroupData.push(preprocessedGroup.data); + } - this.setOptions(options); - } + // 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; + } - TimeAxis.prototype = new Component(); + // 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)) + } - /** - * Set options for the TimeAxis. - * Parameters will be merged in current options. - * @param {Object} options Available options: - * {string} [orientation] - * {boolean} [showMinorLabels] - * {boolean} [showMajorLabels] - */ - TimeAxis.prototype.setOptions = function(options) { - if (options) { - // copy all options that we know - util.selectiveExtend(['orientation', 'showMinorLabels', 'showMajorLabels'], this.options, options); + // draw the groups + for (i = 0; i < groupIds.length; i++) { + group = this.groups[groupIds[i]]; + if (group.options.style == 'line') { + this._drawLineGraph(processedGroupData[i], group); + } + else { + this._drawBarGraph (processedGroupData[i], group); + } + } + } } + + // cleanup unused svg elements + DOMutil.cleanupElements(this.svgElements); }; /** - * Create the HTML DOM for the TimeAxis + * 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 */ - TimeAxis.prototype._create = function() { - this.dom.foreground = document.createElement('div'); - this.dom.background = document.createElement('div'); + 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'; - this.dom.foreground.className = 'timeaxis foreground'; - this.dom.background.className = 'timeaxis background'; - }; + // 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.options.yAxisOrientation == 'right') { + orientation = 'right'; + } - /** - * Destroy the TimeAxis - */ - TimeAxis.prototype.destroy = function() { - // remove from DOM - if (this.dom.foreground.parentNode) { - this.dom.foreground.parentNode.removeChild(this.dom.foreground); + 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; + } + } + if (yAxisLeftUsed == true) { + this.yAxisLeft.setRange(minLeft, maxLeft); + } + if (yAxisRightUsed == true) { + this.yAxisRight.setRange(minRight, maxRight); + } } - if (this.dom.background.parentNode) { - this.dom.background.parentNode.removeChild(this.dom.background); + + 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; } - this.body = null; + this.yAxisRight.master = !yAxisLeftUsed; + + if (this.yAxisRight.master == false) { + if (yAxisRightUsed == true) { + this.yAxisLeft.lineOffset = this.yAxisRight.width; + } + changeCalled = this.yAxisLeft.redraw() || changeCalled; + this.yAxisRight.stepPixelsForced = this.yAxisLeft.stepPixels; + changeCalled = this.yAxisRight.redraw() || changeCalled; + } + else { + changeCalled = this.yAxisRight.redraw() || changeCalled; + } + return changeCalled; }; /** - * Repaint the component - * @return {boolean} Returns true if the component is resized + * 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 */ - TimeAxis.prototype.redraw = function () { - var options = this.options, - props = this.props, - foreground = this.dom.foreground, - background = this.dom.background; + 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; + }; - // 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); - // 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 + /** + * draw a bar graph + * @param datapoints + * @param group + */ + 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; + var width = group.options.barChart.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); + if (group.options.barChart.align == 'left') {offset -= 0.5*width;} + else if (group.options.barChart.align == 'right') {offset += 0.5*width;} - foreground.style.height = this.props.height + 'px'; + for (var i = 0; i < dataset.length; i++) { + // dynammically downscale the width so there is no overlap up to 1/10th the original width + 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 < width) {width = coreDistance < minWidth ? minWidth : coreDistance;} - this._repaintLabels(); + DOMutil.drawBar(dataset[i].x + offset, dataset[i].y, width, group.zeroPosition - dataset[i].y, group.className + ' bar', this.svgElements, this.svg); + } - // 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); - } - else { - this.body.dom.backgroundVertical.appendChild(background) + // draw points + if (group.options.drawPoints.enabled == true) { + this._drawPoints(dataset, group, this.svgElements, this.svg, offset); + } + } } - - return this._isResized() || parentChanged; }; + /** - * Repaint major and minor text labels and vertical grid lines - * @private + * draw a line graph + * + * @param datapoints + * @param group */ - 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 + 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); - if (this.options.showMinorLabels) { - this._repaintMinorText(x, step.getLabelMinor(), orientation); - } + // construct path from dataset + if (group.options.catmullRom.enabled == true) { + d = this._catmullRom(dataset, group); + } + else { + d = this._linear(dataset); + } - if (isMajor && this.options.showMajorLabels) { - if (x > 0) { - if (xFirstMajorLabel == undefined) { - xFirstMajorLabel = x; + // 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; } - this._repaintMajorText(x, step.getLabelMajor(), orientation); + 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); } - this._repaintMajorLine(x, orientation); - } - else { - this._repaintMinorLine(x, orientation); - } - - step.next(); - } - - // 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); - } - } + // copy properties to path for drawing. + path.setAttributeNS(null, "d", "M" + d); - // 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); + // draw points + if (group.options.drawPoints.enabled == true) { + this._drawPoints(dataset, group, this.svgElements, this.svg); } } - }); + } }; /** - * Create a minor label for the axis at position x - * @param {Number} x - * @param {String} text - * @param {String} orientation "top" or "bottom" (default) - * @private + * draw the data points + * + * @param dataset + * @param JSONcontainer + * @param svg + * @param group */ - TimeAxis.prototype._repaintMinorText = function (x, text, orientation) { - // reuse redundant label - var label = this.dom.redundant.minorTexts.shift(); - - 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); + 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.dom.minorTexts.push(label); + }; - 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 - }; /** - * Create a Major label for the axis at position x - * @param {Number} x - * @param {String} text - * @param {String} orientation "top" or "bottom" (default) + * 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._repaintMajorText = function (x, text, orientation) { - // reuse redundant label - var label = this.dom.redundant.majorTexts.shift(); + LineGraph.prototype._preprocessData = function (datapoints, group) { + var extractedData = []; + var xValue, yValue; + var toScreen = this.body.util.toScreen; - 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); + var increment = 1; + var amountOfPoints = datapoints.length; + + 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.dom.majorTexts.push(label); - label.childNodes[0].nodeValue = text; - //label.title = title; // TODO: this is a heavy operation + 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; + } - label.style.top = (orientation == 'top') ? '0' : (this.props.minorLabelHeight + 'px'); - label.style.left = x + 'px'; + // extractedData.sort(function (a,b) {return a.x - b.x;}); + return {min: yMin, max: yMax, data: extractedData}; }; /** - * Create a minor line for the axis at position x - * @param {Number} x - * @param {String} orientation "top" or "bottom" (default) + * 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._repaintMinorLine = function (x, orientation) { - // reuse redundant line - var line = this.dom.redundant.minorLines.shift(); + LineGraph.prototype._convertYvalues = function (datapoints, group) { + var extractedData = []; + var xValue, yValue; + var axis = this.yAxisLeft; + var svgHeight = Number(this.svg.style.height.replace("px","")); - if (!line) { - // create vertical line - line = document.createElement('div'); - line.className = 'grid vertical minor'; - this.dom.background.appendChild(line); + if (group.options.yAxisOrientation == 'right') { + axis = this.yAxisRight; } - this.dom.minorLines.push(line); - var props = this.props; - if (orientation == 'top') { - line.style.top = props.majorLabelHeight + 'px'; - } - else { - line.style.top = this.body.domProps.top.height + 'px'; + 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}); } - line.style.height = props.minorLineHeight + 'px'; - line.style.left = (x - props.minorLineWidth / 2) + 'px'; + + group.setZeroPosition(Math.min(svgHeight, axis.convertValue(0))); + + // extractedData.sort(function (a,b) {return a.x - b.x;}); + return extractedData; }; + /** - * Create a Major line for the axis at position x - * @param {Number} x - * @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._repaintMajorLine = function (x, orientation) { - // reuse redundant line - var line = this.dom.redundant.majorLines.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 (!line) { - // create vertical line - line = document.createElement('DIV'); - line.className = 'grid vertical major'; - this.dom.background.appendChild(line); - } - this.dom.majorLines.push(line); + p0 = (i == 0) ? data[0] : data[i-1]; + p1 = data[i]; + p2 = data[i+1]; + p3 = (i + 2 < length) ? data[i+2] : p2; - var props = this.props; - if (orientation == 'top') { - line.style.top = '0'; - } - else { - line.style.top = this.body.domProps.top.height + 'px'; + + // 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 + " "; } - line.style.left = (x - props.majorLineWidth / 2) + 'px'; - line.style.height = props.majorLineHeight + 'px'; + + return d; }; /** - * 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. + * 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._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. + LineGraph.prototype._catmullRom = function(data, group) { + var alpha = group.options.catmullRom.alpha; + if (alpha == 0 || alpha === undefined) { + return this._catmullRomUniform(data); + } + 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++) { - // 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'; + p0 = (i == 0) ? data[0] : data[i-1]; + p1 = data[i]; + p2 = data[i+1]; + p3 = (i + 2 < length) ? data[i+2] : p2; - 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; + 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)); - // 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'; + // 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.dom.measureCharMajor.appendChild(document.createTextNode('0')); - this.dom.foreground.appendChild(this.dom.measureCharMajor); + // [ 0 1 0 0 ] + // [ -d2pow2a/N A/N d1pow2a/N 0 ] + // [ 0 d3pow2a/M B/M -d2pow2a/M ] + // [ 0 0 1 0 ] + + 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); + + 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;} + + 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)}; + + 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(); - - this.autoScale = true; - this.scale = TimeStep.SCALE.DAY; - this.step = 1; + 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 + }; - // initialize the range - this.setRange(start, end, minimumStep); - } + this.defaultOptions = { + orientation: 'bottom', // supported: 'top', 'bottom' + // TODO: implement timeaxis orientations 'left' and 'right' + showMinorLabels: true, + showMajorLabels: true + }; + this.options = util.extend({}, this.defaultOptions); - /// enum scale - TimeStep.SCALE = { - MILLISECOND: 1, - SECOND: 2, - MINUTE: 3, - HOUR: 4, - DAY: 5, - WEEKDAY: 6, - MONTH: 7, - YEAR: 8 - }; + this.body = body; + // create the HTML DOM + this._create(); - /** - * Set a new range - * If minimumStep is provided, the step size is chosen as close as possible - * to the minimumStep but larger than minimumStep. If minimumStep is not - * provided, the scale is set to 1 DAY. - * The minimumStep should correspond with the onscreen size of about 6 characters - * @param {Date} [start] The start date and time. - * @param {Date} [end] The end date and time. - * @param {int} [minimumStep] Optional. Minimum step size in milliseconds - */ - TimeStep.prototype.setRange = function(start, end, minimumStep) { - if (!(start instanceof Date) || !(end instanceof Date)) { - throw "No legal start or end date in method setRange"; - } + this.setOptions(options); + } - this._start = (start != undefined) ? new Date(start.valueOf()) : new Date(); - this._end = (end != undefined) ? new Date(end.valueOf()) : new Date(); + TimeAxis.prototype = new Component(); - if (this.autoScale) { - this.setMinimumStep(minimumStep); + /** + * Set options for the TimeAxis. + * Parameters will be merged in current options. + * @param {Object} options Available options: + * {string} [orientation] + * {boolean} [showMinorLabels] + * {boolean} [showMajorLabels] + */ + 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) } - }; + return this._isResized() || parentChanged; + }; /** - * Get the current datetime - * @return {Date} current The current date + * Repaint major and minor text labels and vertical grid lines + * @private */ - TimeStep.prototype.getCurrent = function() { - return this.current; - }; + TimeAxis.prototype._repaintLabels = function () { + var orientation = this.options.orientation; - /** - * 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. - */ - TimeStep.prototype.setScale = function(newScale, newStep) { - this.scale = newScale; + // 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; - if (newStep > 0) { - this.step = newStep; + // 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); + } + + step.next(); } - this.autoScale = false; + // 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); + } + } + + // 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); + } + } + }); }; /** - * Enable or disable autoscaling - * @param {boolean} enable If true, autoascaling is set true + * 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.setAutoScale = function (enable) { - this.autoScale = enable; - }; + TimeAxis.prototype._repaintMinorText = function (x, text, orientation) { + // reuse redundant label + var label = this.dom.redundant.minorTexts.shift(); + + 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); + + 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 + }; /** - * Automatically determine the scale that bests fits the provided minimum step - * @param {Number} [minimumStep] The minimum step size in milliseconds + * 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.setMinimumStep = function(minimumStep) { - if (minimumStep == undefined) { - return; + 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); - 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); + label.childNodes[0].nodeValue = text; + //label.title = title; // TODO: this is a heavy operation - // 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;} + label.style.top = (orientation == 'top') ? '0' : (this.props.minorLabelHeight + 'px'); + label.style.left = x + 'px'; }; /** - * 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 line for the axis at position x + * @param {Number} x + * @param {String} orientation "top" or "bottom" (default) + * @private */ - TimeStep.prototype.snap = function(date) { - var clone = new Date(date.valueOf()); + TimeAxis.prototype._repaintMinorLine = function (x, orientation) { + // reuse redundant line + var line = this.dom.redundant.minorLines.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 (!line) { + // create vertical line + line = document.createElement('div'); + line.className = 'grid vertical minor'; + this.dom.background.appendChild(line); } - 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.minorLines.push(line); - 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); + var props = this.props; + if (orientation == 'top') { + line.style.top = props.majorLabelHeight + 'px'; } - 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 { + line.style.top = this.body.domProps.top.height + 'px'; } - 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; + line.style.height = props.minorLineHeight + 'px'; + line.style.left = (x - props.minorLineWidth / 2) + 'px'; }; /** - * 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 line for the axis at position x + * @param {Number} x + * @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._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); + 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'; + }; /** - * 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 + * 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 */ - TimeStep.prototype.getLabelMinor = function(date) { - if (date == undefined) { - date = this.current; + 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'; + + 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; - 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 ''; + // 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; }; - /** - * 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 + * 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 */ - TimeStep.prototype.getLabelMajor = function(date) { - if (date == undefined) { - date = this.current; - } - - //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 ''; - } + TimeAxis.prototype.snap = function(date) { + return this.step.snap(date); }; - module.exports = TimeStep; + module.exports = TimeAxis; /***/ }, -/* 26 */ +/* 28 */ /***/ function(module, exports, __webpack_require__) { - var util = __webpack_require__(1); - var Component = __webpack_require__(22); + var Hammer = __webpack_require__(41); /** - * A current time bar - * @param {{range: Range, dom: Object, domProps: Object}} body - * @param {Object} [options] Available parameters: - * {Boolean} [showCurrentTime] - * @constructor CurrentTime - * @extends Component + * @constructor Item + * @param {Object} data Object containing (optional) parameters type, + * start, end, content, group, className. + * @param {{toScreen: function, toTime: function}} conversion + * Conversion functions from time to screen and vice versa + * @param {Object} options Configuration options + * // TODO: describe available options */ - function CurrentTime (body, options) { - this.body = body; - - // default options - this.defaultOptions = { - showCurrentTime: true - }; - this.options = util.extend({}, this.defaultOptions); + function Item (data, conversion, options) { + this.id = null; + this.parent = null; + this.data = data; + this.dom = null; + this.conversion = conversion || {}; + this.options = options || {}; - this._create(); + this.selected = false; + this.displayed = false; + this.dirty = true; - this.setOptions(options); + this.top = null; + this.left = null; + this.width = null; + this.height = null; } - CurrentTime.prototype = new Component(); - /** - * Create the HTML DOM for the current time bar - * @private + * Select current item */ - 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.bar = bar; + Item.prototype.select = function() { + this.selected = true; + if (this.displayed) this.redraw(); }; /** - * Destroy the CurrentTime bar + * Unselect 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.unselect = function() { + this.selected = false; + if (this.displayed) this.redraw(); }; /** - * Set options for the component. Options will be merged in current options. - * @param {Object} options Available parameters: - * {boolean} [showCurrentTime] + * Set a parent for the item + * @param {ItemSet | Group} parent */ - CurrentTime.prototype.setOptions = function(options) { - if (options) { - // copy all options that we know - util.selectiveExtend(['showCurrentTime'], this.options, options); + Item.prototype.setParent = function(parent) { + if (this.displayed) { + this.hide(); + this.parent = parent; + if (this.parent) { + this.show(); + } + } + else { + this.parent = parent; } }; /** - * Repaint the component - * @return {boolean} Returns true if the component is resized + * 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 */ - 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(); - } - - 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(); - } - + 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 */ - - 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(); + Item.prototype.redraw = 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 horizontally */ - CustomTime.prototype.setOptions = function(options) { - if (options) { - // copy all options that we know - util.selectiveExtend(['showCustomTime'], this.options, options); - } + Item.prototype.repositionX = function() { + // should be implemented by the item }; /** - * Create the DOM for the custom time - * @private + * Reposition the Item vertically */ - 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; - - 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)); + Item.prototype.repositionY = function() { + // should be implemented by the item }; /** - * Destroy the CustomTime bar + * Repaint a delete button on the top right of the item when the item is selected + * @param {HTMLElement} anchor + * @protected */ - CustomTime.prototype.destroy = function () { - this.options.showCustomTime = false; - this.redraw(); // will remove the bar from the DOM + Item.prototype._repaintDeleteButton = function (anchor) { + if (this.selected && this.options.editable.remove && !this.dom.deleteButton) { + // create and show button + var me = this; - this.hammer.enable(false); - this.hammer = null; + var deleteButton = document.createElement('div'); + deleteButton.className = 'delete'; + deleteButton.title = 'Delete this item'; - this.body = null; + 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; + } }; + module.exports = Item; + + +/***/ }, +/* 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; + } - module.exports = CustomTime; + // 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; + } -/***/ }, -/* 28 */ -/***/ function(module, exports, __webpack_require__) { + // 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; - 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.dirty = false; + } + this._repaintDeleteButton(dom.box); + }; - var UNGROUPED = '__ungrouped__'; // reserved group id for ungrouped items + /** + * 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(); + } + }; /** - * 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 + * Hide the item from the DOM (when visible) */ - function ItemSet(body, options) { - this.body = body; + ItemBox.prototype.hide = function() { + if (this.displayed) { + var dom = this.dom; - this.defaultOptions = { - type: null, // 'box', 'point', 'range' - orientation: 'bottom', // 'top' or 'bottom' - align: 'center', // alignment of box items - stack: true, - groupOrder: null, + 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); - selectable: true, - editable: { - updateTime: false, - updateGroup: false, - add: false, - remove: false - }, + this.top = null; + this.left = null; - onAdd: function (item, callback) { - callback(item); - }, - onUpdate: function (item, callback) { - callback(item); - }, - onMove: function (item, callback) { - callback(item); - }, - onRemove: function (item, callback) { - callback(item); - }, + this.displayed = false; + } + }; - margin: { - item: { - horizontal: 10, - vertical: 10 - }, - axis: 20 - }, - padding: 5 - }; + /** + * 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; - // options is shared by this ItemSet and all its items - this.options = util.extend({}, this.defaultOptions); + // 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; + } - // options for getting items from the DataSet with the correct type - this.itemOptions = { - type: {start: 'Date', end: 'Date'} - }; + // reposition box + box.style.left = this.left + 'px'; - this.conversion = { - toScreen: body.util.toScreen, - toTime: body.util.toTime - }; - this.dom = {}; - this.props = {}; - this.hammer = null; + // reposition line + line.style.left = (start - this.props.line.width / 2) + 'px'; - var me = this; - this.itemsData = null; // DataSet - this.groupsData = null; // DataSet + // reposition dot + dot.style.left = (start - this.props.dot.width / 2) + 'px'; + }; - // 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); - } - }; + /** + * Reposition the item vertically + * @Override + */ + ItemBox.prototype.repositionY = function() { + var orientation = this.options.orientation, + box = this.dom.box, + line = this.dom.line, + dot = this.dom.dot; - // 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); - } - }; + if (orientation == 'top') { + box.style.top = (this.top || 0) + 'px'; - this.items = {}; // object with an Item for every data item - this.groups = {}; // Group object for every group - this.groupIds = []; + 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; - this.selection = []; // list with the ids of all selected nodes - this.stackDirty = true; // if true, all items will be restacked on next redraw + box.style.top = (this.parent.height - this.top - this.height || 0) + 'px'; + line.style.top = (itemSetHeight - lineHeight) + 'px'; + line.style.bottom = '0'; + } - this.touchParams = {}; // stores properties while dragging - // create the HTML DOM + dot.style.top = (-this.props.dot.height / 2) + 'px'; + }; - this._create(); + module.exports = ItemBox; - this.setOptions(options); + +/***/ }, +/* 30 */ +/***/ function(module, exports, __webpack_require__) { + + var Item = __webpack_require__(28); + + /** + * @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 + }, + 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); } - 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; + ItemPoint.prototype.redraw = function() { + var dom = this.dom; + if (!dom) { + // create DOM + this.dom = {}; + dom = this.dom; - // create background panel - var background = document.createElement('div'); - background.className = 'background'; - frame.appendChild(background); - this.dom.background = background; + // background box + dom.point = document.createElement('div'); + // className is updated in redraw() - // create foreground panel - var foreground = document.createElement('div'); - foreground.className = 'foreground'; - frame.appendChild(foreground); - this.dom.foreground = foreground; + // contents box, right from the dot + dom.content = document.createElement('div'); + dom.content.className = 'content'; + dom.point.appendChild(dom.content); - // create axis panel - var axis = document.createElement('div'); - axis.className = 'axis'; - this.dom.axis = axis; + // dot at start + dom.dot = document.createElement('div'); + dom.point.appendChild(dom.dot); - // create labelset - var labelSet = document.createElement('div'); - labelSet.className = 'labelset'; - this.dom.labelSet = labelSet; + // attach this item as attribute + dom.point['timeline-item'] = this; + } - // create ungrouped Group - this._updateUngrouped(); + // 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; - // 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 - }); + // 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); + } - // 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)); + this.dirty = true; + } - // single select (or unselect) when tapping an item - this.hammer.on('tap', this._onSelectItem.bind(this)); + // update title + if (this.data.title != this.title) { + dom.point.title = this.data.title; + this.title = this.data.title; + } - // multi select when holding mouse/touch, or on ctrl+click - this.hammer.on('hold', this._onMultiSelectItem.bind(this)); + // 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; - // add item on doubletap - this.hammer.on('doubletap', this._onAddItem.bind(this)); + this.dirty = true; + } - // attach to the DOM - this.show(); + // 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; + + // resize contents + dom.content.style.marginLeft = 2 * this.props.dot.width + 'px'; + //dom.content.style.marginRight = ... + 'px'; // TODO: margin right + + dom.dot.style.top = ((this.height - this.props.dot.height) / 2) + 'px'; + dom.dot.style.left = (this.props.dot.width / 2) + 'px'; + + this.dirty = false; + } + + this._repaintDeleteButton(dom.point); }; /** - * 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. + * Show the item in the DOM (when not already visible). The items DOM will + * be created when needed. */ - 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); - - 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); - } - } - } - } - - 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); - } - } - - // 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); - - // force the itemSet to refresh: options like orientation and margins may be changed - this.markDirty(); + ItemPoint.prototype.show = function() { + if (!this.displayed) { + this.redraw(); } }; /** - * Mark the ItemSet dirty so it will refresh everything with next redraw + * Hide the item from the DOM (when visible) */ - ItemSet.prototype.markDirty = function() { - this.groupIds = []; - this.stackDirty = true; + ItemPoint.prototype.hide = function() { + if (this.displayed) { + if (this.dom.point.parentNode) { + this.dom.point.parentNode.removeChild(this.dom.point); + } + + this.top = null; + this.left = null; + + this.displayed = false; + } }; /** - * Destroy the ItemSet + * Reposition the item horizontally + * @Override */ - ItemSet.prototype.destroy = function() { - this.hide(); - this.setItems(null); - this.setGroups(null); + ItemPoint.prototype.repositionX = function() { + var start = this.conversion.toScreen(this.data.start); - this.hammer = null; + this.left = start - this.props.dot.width; - this.body = null; - this.conversion = null; + // reposition point + this.dom.point.style.left = this.left + 'px'; }; /** - * Hide the component from the DOM + * Reposition the item vertically + * @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.repositionY = function() { + var orientation = this.options.orientation, + point = this.dom.point; - // remove the axis with dots - if (this.dom.axis.parentNode) { - this.dom.axis.parentNode.removeChild(this.dom.axis); + if (orientation == 'top') { + point.style.top = this.top + 'px'; } - - // remove the labelset containing all group labels - if (this.dom.labelSet.parentNode) { - this.dom.labelSet.parentNode.removeChild(this.dom.labelSet); + else { + point.style.top = (this.parent.height - this.top - this.height) + 'px'; } }; - /** - * 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); - } + module.exports = ItemPoint; - // 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); - } - }; +/***/ }, +/* 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); - return ids; - }; + // attach this item as attribute + dom.box['timeline-item'] = this; + } - /** - * 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; + // 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); } - }; - - /** - * Repaint the component - * @return {boolean} Returns true if the component is resized - */ - 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; + this.displayed = true; - // update class name - frame.className = 'itemset' + (editable ? ' editable' : ''); + // 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); + } - // reorder the groups (if needed) - resized = this._orderGroups() || resized; + this.dirty = true; + } - // 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; + // update title + if (this.data.title != this.title) { + dom.box.title = this.data.title; + this.title = this.data.title; + } - // 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; + // 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; - // update frame height - frame.style.height = asSize(height); + this.dirty = 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; + // recalculate size + if (this.dirty) { + // determine from css whether this box has overflow + this.overflow = window.getComputedStyle(dom.content).overflow !== 'hidden'; - // 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.props.content.width = this.dom.content.offsetWidth; + this.height = this.dom.box.offsetHeight; - // check if this component is resized - resized = this._isResized() || resized; + this.dirty = false; + } - return resized; + this._repaintDeleteButton(dom.box); + this._repaintDragLeft(); + this._repaintDragRight(); }; /** - * Get the first group, aligned with the axis - * @return {Group | null} firstGroup - * @private + * Show the item in the DOM (when not already visible). The items DOM will + * be created when needed. */ - 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]; - - return firstGroup || null; + ItemRange.prototype.show = function() { + if (!this.displayed) { + this.redraw(); + } }; /** - * Create or delete the group holding all ungrouped items. This group is used when - * there are no groups specified. - * @protected + * Hide the item from the DOM (when visible) + * @return {Boolean} changed */ - ItemSet.prototype._updateUngrouped = function() { - var ungrouped = this.groups[UNGROUPED]; + ItemRange.prototype.hide = function() { + if (this.displayed) { + var box = this.dom.box; - if (this.groupsData) { - // remove the group holding all ungrouped items - if (ungrouped) { - ungrouped.hide(); - delete this.groups[UNGROUPED]; + if (box.parentNode) { + box.parentNode.removeChild(box); } - } - 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; - for (var itemId in this.items) { - if (this.items.hasOwnProperty(itemId)) { - ungrouped.add(this.items[itemId]); - } - } + this.top = null; + this.left = null; - ungrouped.show(); - } + this.displayed = false; } }; /** - * Get the element for the labelset - * @return {HTMLElement} labelSet - */ - ItemSet.prototype.getLabelSet = function() { - return this.dom.labelSet; - }; - - /** - * Set items - * @param {vis.DataSet | null} items + * Reposition the item horizontally + * @Override */ - ItemSet.prototype.setItems = function(items) { - var me = this, - ids, - oldItemsData = this.itemsData; + // TODO: delete the old function + 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; - // replace the dataset - if (!items) { - this.itemsData = null; - } - else if (items instanceof DataSet || items instanceof DataView) { - this.itemsData = items; + // limit the width of the this, as browsers cannot draw very wide divs + if (start < -parentWidth) { + start = -parentWidth; } - else { - throw new TypeError('Data must be an instance of DataSet or DataView'); + if (end > 2 * parentWidth) { + end = 2 * parentWidth; } + var boxWidth = Math.max(end - start, 1); - if (oldItemsData) { - // unsubscribe from old dataset - util.forEach(this.itemListeners, function (callback, event) { - oldItemsData.off(event, callback); - }); + 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); - // remove all drawn items - ids = oldItemsData.getIds(); - this._onRemove(ids); + 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; + } - if (this.itemsData) { - // subscribe to new dataset - var id = this.id; - util.forEach(this.itemListeners, function (callback, event) { - me.itemsData.on(event, callback, id); - }); - - // add all new items - ids = this.itemsData.getIds(); - this._onAdd(ids); - - // update the group holding all ungrouped items - this._updateUngrouped(); + 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'; }; /** - * Get the current items - * @returns {vis.DataSet | null} - */ - ItemSet.prototype.getItems = function() { - return this.itemsData; - }; - - /** - * Set groups - * @param {vis.DataSet} groups + * Reposition the item vertically + * @Override */ - ItemSet.prototype.setGroups = function(groups) { - var me = this, - ids; - - // 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 - } + ItemRange.prototype.repositionY = function() { + var orientation = this.options.orientation, + box = this.dom.box; - // replace the dataset - if (!groups) { - this.groupsData = null; - } - else if (groups instanceof DataSet || groups instanceof DataView) { - this.groupsData = groups; + if (orientation == 'top') { + box.style.top = this.top + 'px'; } else { - throw new TypeError('Data must be an instance of DataSet or DataView'); - } - - 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); + box.style.top = (this.parent.height - this.top - this.height) + 'px'; } - - // 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'); }; /** - * Get the current groups - * @returns {vis.DataSet | null} groups + * Repaint a drag area on the left side of the range when the range is selected + * @protected */ - ItemSet.prototype.getGroups = function() { - return this.groupsData; - }; + 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; - /** - * 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(); + // TODO: this should be redundant? + Hammer(dragLeft, { + preventDefault: true + }).on('drag', function () { + //console.log('drag left') + }); - 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); - } - }); + 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; } }; /** - * Handle updated items - * @param {Number[]} ids + * Repaint a drag area on the right side of the range when the range is selected * @protected */ - ItemSet.prototype._onUpdate = function(ids) { - var me = this; - - 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'); - - var constructor = ItemSet.types[type]; + 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; - 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); - } - } + // TODO: this should be redundant? + Hammer(dragRight, { + preventDefault: true + }).on('drag', function () { + //console.log('drag right') + }); - 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 + '"'); - } + 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._order(); - this.stackDirty = true; // force re-stacking of all items next redraw - this.body.emitter.emit('change'); + this.dom.dragRight = null; + } }; - /** - * Handle added items - * @param {Number[]} ids - * @protected - */ - ItemSet.prototype._onAdd = ItemSet.prototype._onUpdate; + module.exports = ItemRange; - /** - * 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); - } - }); - if (count) { - // update order - this._order(); - this.stackDirty = true; // force re-stacking of all items next redraw - this.body.emitter.emit('change'); - } - }; +/***/ }, +/* 32 */ +/***/ function(module, exports, __webpack_require__) { - /** - * 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(); - }); - }; + var Emitter = __webpack_require__(45); + var Hammer = __webpack_require__(41); + var mousetrap = __webpack_require__(46); + var util = __webpack_require__(1); + var hammerUtil = __webpack_require__(42); + 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__(44); - /** - * Handle updated groups - * @param {Number[]} ids - * @private - */ - ItemSet.prototype._onUpdateGroups = function(ids) { - this._onAddGroups(ids); - }; + // Load custom shapes into CanvasRenderingContext2D + __webpack_require__(43); /** - * Handle changed groups - * @param {Number[]} ids - * @private + * @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._onAddGroups = function(ids) { - var me = this; - - ids.forEach(function (id) { - var groupData = me.groupsData.get(id); - var group = me.groups[id]; + function Network (container, data, options) { + if (!(this instanceof Network)) { + throw new SyntaxError('Constructor must be called with the new operator'); + } - if (!group) { - // check for reserved ids - if (id == UNGROUPED) { - throw new Error('Illegal group id. ' + id + ' is a reserved id.'); - } + this._initializeMixinLoaders(); - var groupOptions = Object.create(me.options); - util.extend(groupOptions, { - height: null - }); + // create variables and set default values + this.containerElement = container; + this.width = '100%'; + this.height = '100%'; - group = new Group(id, groupData, me); - me.groups[id] = group; + // 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 - // 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.stabilize = true; // stabilize before displaying the network + this.selectable = true; + this.initializing = true; + + // these functions are triggered when the dataset is edited + this.triggerFunctions = {add:null,edit:null,editEdge:null,connect:null,del:null}; + + + // set constant values + this.constants = { + nodes: { + 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 + 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 + }; + this.hoverObj = {nodes:{},edges:{}}; + this.controlNodesActive = false; - group.order(); - group.show(); - } - else { - // update group - group.setData(groupData); - } + // 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(); }); - this.body.emitter.emit('change'); - }; + // keyboard navigation variables + this.xIncrement = 0; + this.yIncrement = 0; + this.zoomIncrement = 0; - /** - * Handle removed groups - * @param {Number[]} ids - * @private - */ - ItemSet.prototype._onRemoveGroups = function(ids) { - var groups = this.groups; - ids.forEach(function (id) { - var group = groups[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(); - if (group) { - group.hide(); - delete groups[id]; - } - }); + // apply options + this._setTranslation(this.frame.clientWidth / 2, this.frame.clientHeight / 2); + this._setScale(1); + this.setOptions(options); - this.markDirty(); + // other vars + this.freezeSimulation = false;// freeze the simulation + this.cachedFunctions = {}; - this.body.emitter.emit('change'); - }; + // 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 - /** - * 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 - }); - - 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(); - }); + // 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 - // show the groups again, attach them to the DOM in correct order - groupIds.forEach(function (groupId) { - groups[groupId].show(); - }); + // datasets or dataviews + this.nodesData = null; // A DataSet or DataView + this.edgesData = null; // A DataSet or DataView - this.groupIds = groupIds; + // 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(); } + }; - return changed; + // 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 { - return false; + // zoom so all data will fit on the screen, if clustering is enabled, we do not want start to be called here. + if (this.stabilize == false) { + this.zoomExtent(true,this.constants.clustering.enabled); + } } - }; - /** - * Add a new item - * @param {Item} item - * @private - */ - ItemSet.prototype._addItem = function(item) { - this.items[item.id] = item; + // if clustering is disabled, the simulation will have started in the setData function + if (this.constants.clustering.enabled) { + this.startWithClustering(); + } + } - // add to group - var groupId = this.groupsData ? item.data.group : UNGROUPED; - var group = this.groups[groupId]; - if (group) group.add(item); - }; + // Extend Network with an Emitter mixin + Emitter(Network.prototype); /** - * Update an existing item - * @param {Item} item - * @param {Object} itemData + * 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._updateItem = function(item, itemData) { - var oldGroupId = item.data.group; + Network.prototype._getScriptPath = function() { + var scripts = document.getElementsByTagName( 'script' ); - item.data = itemData; - if (item.displayed) { - item.redraw(); + // 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); + } } - // update group - if (oldGroupId != item.data.group) { - var oldGroup = this.groups[oldGroupId]; - if (oldGroup) oldGroup.remove(item); - - var groupId = this.groupsData ? item.data.group : UNGROUPED; - var group = this.groups[groupId]; - if (group) group.add(item); - } + return null; }; + /** - * 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 + * Find the center position of the network * @private */ - 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); - - // remove from group - var groupId = this.groupsData ? item.data.group : UNGROUPED; - var group = this.groups[groupId]; - if (group) group.remove(item); + 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}; }; + /** - * Create an array containing all items being a range (having an end date) - * @param array - * @returns {Array} + * @param {object} range = {minX: minX, maxX: maxX, minY: minY, maxY: maxY}; + * @returns {{x: number, y: number}} * @private */ - ItemSet.prototype._constructByEndArray = function(array) { - var endArray = []; - - for (var i = 0; i < array.length; i++) { - if (array[i] instanceof ItemRange) { - endArray.push(array[i]); - } - } - return endArray; + Network.prototype._findCenter = function(range) { + return {x: (0.5 * (range.maxX + range.minX)), + y: (0.5 * (range.maxY + range.minY))}; }; + /** - * 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 + * center the network * - * @param {Event} event - * @private + * @param {object} range = {minX: minX, maxX: maxX, minY: minY, maxY: maxY}; */ - ItemSet.prototype._onTouch = function (event) { - // store the touched item, used in _onDragStart - this.touchParams.item = ItemSet.itemFromTarget(event); + Network.prototype._centerNetwork = function(range) { + var center = this._findCenter(range); + + center.x *= this.scale; + center.y *= this.scale; + center.x -= 0.5 * this.frame.canvas.clientWidth; + center.y -= 0.5 * this.frame.canvas.clientHeight; + + this._setTranslation(-center.x,-center.y); // set at 0,0 }; + /** - * Start dragging the selected events - * @param {Event} event - * @private + * 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. */ - ItemSet.prototype._onDragStart = function (event) { - if (!this.options.editable.updateTime && !this.options.editable.updateGroup) { - return; + Network.prototype.zoomExtent = function(initialZoom, disableStart) { + if (initialZoom === undefined) { + initialZoom = false; + } + if (disableStart === undefined) { + disableStart = false; } - var item = this.touchParams.item || null, - me = this, - props; - - if (item && item.selected) { - var dragLeftItem = event.target.dragLeftItem; - var dragRightItem = event.target.dragRightItem; - - if (dragLeftItem) { - props = { - item: dragLeftItem - }; + var range = this._getRange(); + var zoomLevel; - if (me.options.editable.updateTime) { - props.start = item.data.start.valueOf(); + 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. } - if (me.options.editable.updateGroup) { - if ('group' in item.data) props.group = item.data.group; + 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. } - - this.touchParams.itemProps = [props]; } - else if (dragRightItem) { - props = { - item: dragRightItem - }; - - if (me.options.editable.updateTime) { - props.end = item.data.end.valueOf(); + 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. } - if (me.options.editable.updateGroup) { - if ('group' in item.data) props.group = item.data.group; + 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.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; - } + // 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; - return props; - }); - } + var xZoomLevel = this.frame.canvas.clientWidth / xDistance; + var yZoomLevel = this.frame.canvas.clientHeight / yDistance; - event.stopPropagation(); + zoomLevel = (xZoomLevel <= yZoomLevel) ? xZoomLevel : yZoomLevel; + } + + if (zoomLevel > 1.0) { + zoomLevel = 1.0; + } + + + this._setScale(zoomLevel); + this._centerNetwork(range); + if (disableStart == false) { + this.moving = true; + this.start(); } }; + /** - * Drag selected items - * @param {Event} event + * Update the this.nodeIndices with the most recent node index list * @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._updateNodeIndexList = function() { + this._clearNodeIndexList(); + for (var idx in this.nodes) { + if (this.nodes.hasOwnProperty(idx)) { + this.nodeIndices.push(idx); + } + } + }; - if ('end' in props) { - var end = new Date(props.end + offset); - props.item.data.end = snap ? snap(end) : end; - } - if ('group' in props) { - // drag from one group to another - var group = ItemSet.groupFromTarget(event); - if (group && group.groupId != props.item.data.group) { - var oldGroup = props.item.parent; - oldGroup.remove(props.item); - oldGroup.order(); - group.add(props.item); - group.order(); + /** + * 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; + } - props.item.data.group = group.groupId; - } - } - }); + 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.'); + } - // TODO: implement onMoving handler + // set options + this.setOptions(data && data.options); - this.stackDirty = true; // force re-stacking of all items next redraw - this.body.emitter.emit('change'); + // 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); + } - event.stopPropagation(); + this._putDataInSector(); + if (!disableStart) { + // find a stable position or start animating to a stable position + if (this.stabilize) { + var me = this; + setTimeout(function() {me._stabilize(); me.start();},0) + } + else { + this.start(); + } } }; /** - * End of dragging selected items - * @param {Event} event - * @private + * Set options + * @param {Object} options + * @param {Boolean} [initializeView] | set zoom and translation to default. */ - 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(); + Network.prototype.setOptions = function (options) { + if (options) { + var prop; + // retrieve parameter values + if (options.width !== undefined) {this.width = options.width;} + if (options.height !== undefined) {this.height = options.height;} + if (options.stabilize !== undefined) {this.stabilize = options.stabilize;} + if (options.selectable !== undefined) {this.selectable = options.selectable;} + if (options.freezeForStabilization !== undefined) {this.constants.freezeForStabilization = options.freezeForStabilization;} + if (options.configurePhysics !== undefined){this.constants.configurePhysics = options.configurePhysics;} + if (options.stabilizationIterations !== undefined) {this.constants.stabilizationIterations = options.stabilizationIterations;} + if (options.dragNetwork !== undefined) {this.constants.dragNetwork = options.dragNetwork;} + if (options.dragNodes !== undefined) {this.constants.dragNodes = options.dragNodes;} + if (options.zoomable !== undefined) {this.constants.zoomable = options.zoomable;} + if (options.hover !== undefined) {this.constants.hover = options.hover;} + if (options.hideEdgesOnDrag !== undefined) {this.constants.hideEdgesOnDrag = options.hideEdgesOnDrag;} + if (options.hideNodesOnDrag !== undefined) {this.constants.hideNodesOnDrag = options.hideNodesOnDrag;} - this.touchParams.itemProps.forEach(function (props) { - var id = props.item.id, - itemData = me.itemsData.get(id, me.itemOptions); + // TODO: deprecated since version 3.0.0. Cleanup some day + if (options.dragGraph !== undefined) { + throw new Error('Option dragGraph is renamed to dragNetwork'); + } - 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 (options.labels !== undefined) { + for (prop in options.labels) { + if (options.labels.hasOwnProperty(prop)) { + this.constants.labels[prop] = options.labels[prop]; + } } + } - // 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; - - me.stackDirty = true; // force re-stacking of all items next redraw - me.body.emitter.emit('change'); - } - }); + if (options.onAdd) { + this.triggerFunctions.add = options.onAdd; } - }); - this.touchParams.itemProps = null; - // apply the changes to the data (if there are changes) - if (changes.length) { - dataset.update(changes); + if (options.onEdit) { + this.triggerFunctions.edit = options.onEdit; } - event.stopPropagation(); - } - }; + if (options.onEditEdge) { + this.triggerFunctions.editEdge = options.onEditEdge; + } - /** - * Handle selecting/deselecting an item when tapping it - * @param {Event} event - * @private - */ - ItemSet.prototype._onSelectItem = function (event) { - if (!this.options.selectable) return; + if (options.onConnect) { + this.triggerFunctions.connect = options.onConnect; + } - 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; - } + if (options.onDelete) { + this.triggerFunctions.del = options.onDelete; + } - var oldSelection = this.getSelection(); - - var item = ItemSet.itemFromTarget(event); - var selection = item ? [item.id] : []; - this.setSelection(selection); + if (options.physics) { + if (options.physics.barnesHut) { + this.constants.physics.barnesHut.enabled = true; + for (prop in options.physics.barnesHut) { + if (options.physics.barnesHut.hasOwnProperty(prop)) { + this.constants.physics.barnesHut[prop] = options.physics.barnesHut[prop]; + } + } + } - var newSelection = this.getSelection(); + if (options.physics.repulsion) { + this.constants.physics.barnesHut.enabled = false; + for (prop in options.physics.repulsion) { + if (options.physics.repulsion.hasOwnProperty(prop)) { + this.constants.physics.repulsion[prop] = options.physics.repulsion[prop]; + } + } + } - // 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() - }); - } + 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]; + } + } + } + } - event.stopPropagation(); - }; + if (options.smoothCurves !== undefined) { + if (typeof options.smoothCurves == 'boolean') { + this.constants.smoothCurves.enabled = options.smoothCurves; + } + else { + this.constants.smoothCurves.enabled = true; + for (prop in options.smoothCurves) { + if (options.smoothCurves.hasOwnProperty(prop)) { + this.constants.smoothCurves[prop] = options.smoothCurves[prop]; + } + } + } + } - /** - * Handle creation and updates of an item on double tap - * @param event - * @private - */ - ItemSet.prototype._onAddItem = function (event) { - if (!this.options.selectable) return; - if (!this.options.editable.add) return; + if (options.hierarchicalLayout) { + this.constants.hierarchicalLayout.enabled = true; + for (prop in options.hierarchicalLayout) { + if (options.hierarchicalLayout.hasOwnProperty(prop)) { + this.constants.hierarchicalLayout[prop] = options.hierarchicalLayout[prop]; + } + } + } + else if (options.hierarchicalLayout !== undefined) { + this.constants.hierarchicalLayout.enabled = false; + } - var me = this, - snap = this.body.util.snap || null, - item = ItemSet.itemFromTarget(event); + if (options.clustering) { + this.constants.clustering.enabled = true; + for (prop in options.clustering) { + if (options.clustering.hasOwnProperty(prop)) { + this.constants.clustering[prop] = options.clustering[prop]; + } + } + } + else if (options.clustering !== undefined) { + this.constants.clustering.enabled = false; + } - if (item) { - // update item + if (options.navigation) { + this.constants.navigation.enabled = true; + for (prop in options.navigation) { + if (options.navigation.hasOwnProperty(prop)) { + this.constants.navigation[prop] = options.navigation[prop]; + } + } + } + else if (options.navigation !== undefined) { + this.constants.navigation.enabled = false; + } - // 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); + if (options.keyboard) { + this.constants.keyboard.enabled = true; + for (prop in options.keyboard) { + if (options.keyboard.hasOwnProperty(prop)) { + this.constants.keyboard[prop] = options.keyboard[prop]; + } } - }); - } - 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' - }; + } + else if (options.keyboard !== undefined) { + this.constants.keyboard.enabled = false; + } - // 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 (options.dataManipulation) { + this.constants.dataManipulation.enabled = true; + for (prop in options.dataManipulation) { + if (options.dataManipulation.hasOwnProperty(prop)) { + this.constants.dataManipulation[prop] = options.dataManipulation[prop]; + } + } + this.editMode = this.constants.dataManipulation.initiallyVisible; + } + else if (options.dataManipulation !== undefined) { + this.constants.dataManipulation.enabled = false; } - newItem[this.itemsData.fieldId] = util.randomUUID(); + // TODO: work out these options and document them + if (options.edges) { + for (prop in options.edges) { + if (options.edges.hasOwnProperty(prop)) { + if (typeof options.edges[prop] != "object") { + this.constants.edges[prop] = options.edges[prop]; + } + } + } - var group = ItemSet.groupFromTarget(event); - if (group) { - newItem.group = group.groupId; - } + 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;} + } + } - // 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? + 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;} + } } - }); - } - }; - /** - * Handle selecting/deselecting multiple items when holding an item - * @param {Event} event - * @private - */ - ItemSet.prototype._onMultiSelectItem = function (event) { - if (!this.options.selectable) return; + // Added to support dashed lines + // David Jordan + // 2012-08-08 + if (options.edges.dash) { + if (options.edges.dash.length !== undefined) { + this.constants.edges.dash.length = options.edges.dash.length; + } + if (options.edges.dash.gap !== undefined) { + this.constants.edges.dash.gap = options.edges.dash.gap; + } + if (options.edges.dash.altLength !== undefined) { + this.constants.edges.dash.altLength = options.edges.dash.altLength; + } + } + } - var selection, - item = ItemSet.itemFromTarget(event); + if (options.nodes) { + for (prop in options.nodes) { + if (options.nodes.hasOwnProperty(prop)) { + this.constants.nodes[prop] = options.nodes[prop]; + } + } - 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); + if (options.nodes.color) { + this.constants.nodes.color = util.parseColor(options.nodes.color); + } + + /* + if (options.nodes.widthMin) this.constants.nodes.radiusMin = options.nodes.widthMin; + if (options.nodes.widthMax) this.constants.nodes.radiusMax = options.nodes.widthMax; + */ } - else { - // item is already selected -> deselect it - selection.splice(index, 1); + 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.setSelection(selection); - - this.body.emitter.emit('select', { - items: this.getSelection() - }); - event.stopPropagation(); + 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); + } + } } - }; - /** - * 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 - */ - ItemSet.itemFromTarget = function(event) { - var target = event.target; - while (target) { - if (target.hasOwnProperty('timeline-item')) { - return target['timeline-item']; - } - target = target.parentNode; - } - return null; + // (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.width, this.height); + this.moving = true; + this.start(); + }; /** - * 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 + * 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.groupFromTarget = function(event) { - var target = event.target; - while (target) { - if (target.hasOwnProperty('timeline-group')) { - return target['timeline-group']; - } - target = target.parentNode; + Network.prototype._create = function () { + // remove all elements from the container element. + while (this.containerElement.hasChildNodes()) { + this.containerElement.removeChild(this.containerElement.firstChild); } - return null; + this.frame = document.createElement('div'); + this.frame.className = 'network-frame'; + this.frame.style.position = 'relative'; + this.frame.style.overflow = 'hidden'; + + // 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) ); + + // add the frame to the container element + this.containerElement.appendChild(this.frame); + }; + /** - * 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 + * Binding the keys for keyboard navigation. These functions are defined in the NavigationMixin + * @private */ - ItemSet.itemSetFromTarget = function(event) { - var target = event.target; - while (target) { - if (target.hasOwnProperty('timeline-itemset')) { - return target['timeline-itemset']; - } - target = target.parentNode; + 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"); } - return null; + if (this.constants.dataManipulation.enabled == true) { + this.mousetrap.bind("escape",this._createManipulatorBar.bind(me)); + this.mousetrap.bind("del",this._deleteSelected.bind(me)); + } }; - module.exports = ItemSet; + /** + * Get the pointer location from a touch location + * @param {{pageX: Number, pageY: Number}} touch + * @return {{x: Number, y: Number}} pointer + * @private + */ + Network.prototype._getPointer = function (touch) { + return { + x: touch.pageX - util.getAbsoluteLeft(this.frame.canvas), + y: touch.pageY - util.getAbsoluteTop(this.frame.canvas) + }; + }; + + /** + * 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(); + this._handleTouch(this.drag.pointer); + }; -/***/ }, -/* 29 */ -/***/ function(module, exports, __webpack_require__) { + /** + * handle drag start event + * @private + */ + Network.prototype._onDragStart = function () { + this._handleDragStart(); + }; - var util = __webpack_require__(1); - var stack = __webpack_require__(30); - var ItemRange = __webpack_require__(31); /** - * @constructor Group - * @param {Number | String} groupId - * @param {Object} data - * @param {ItemSet} itemSet + * This function is called by _onDragStart. + * It is separated out because we can then overload it for the datamanipulation system. + * + * @private */ - function Group (groupId, data, itemSet) { - this.groupId = groupId; + 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 - this.itemSet = itemSet; + drag.dragging = true; + drag.selection = []; + drag.translation = this._getTranslation(); + drag.nodeId = null; - this.dom = {}; - this.props = { - label: { - width: 0, - height: 0 + if (node != null) { + drag.nodeId = node.id; + // select the clicked node if not yet selected + if (!node.isSelected()) { + this._selectObject(node,false); } - }; - 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: [] - }; + // 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, - this._create(); + // store original x, y, xFixed and yFixed, make the node temporarily Fixed + x: object.x, + y: object.y, + xFixed: object.xFixed, + yFixed: object.yFixed + }; + + object.xFixed = true; + object.yFixed = true; + + drag.selection.push(s); + } + } + } + }; - this.setData(data); - } /** - * Create DOM elements for the group + * handle drag event * @private */ - Group.prototype._create = function() { - var label = document.createElement('div'); - label.className = 'vlabel'; - this.dom.label = label; - - var inner = document.createElement('div'); - inner.className = 'inner'; - label.appendChild(inner); - this.dom.inner = inner; + Network.prototype._onDrag = function (event) { + this._handleOnDrag(event) + }; - var foreground = document.createElement('div'); - foreground.className = 'group'; - foreground['timeline-group'] = this; - this.dom.foreground = foreground; - - this.dom.background = document.createElement('div'); - this.dom.background.className = 'group'; - - this.dom.axis = document.createElement('div'); - this.dom.axis.className = 'group'; - - // create a hidden marker to detect when the Timelines container is attached - // to the DOM, or the style of a parent of the Timeline is changed from - // display:none is changed to visible. - this.dom.marker = document.createElement('div'); - this.dom.marker.style.visibility = 'hidden'; - this.dom.marker.innerHTML = '?'; - this.dom.background.appendChild(this.dom.marker); - }; /** - * Set the group data for this group - * @param {Object} data Group data, can contain properties content and className + * This function is called by _onDrag. + * It is separated out because we can then overload it for the datamanipulation system. + * + * @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) { - this.dom.inner.innerHTML = content; - } - else { - this.dom.inner.innerHTML = this.groupId; - } - - // update title - this.dom.label.title = data && data.title || ''; - - if (!this.dom.inner.firstChild) { - util.addClassName(this.dom.inner, 'hidden'); - } - else { - util.removeClassName(this.dom.inner, 'hidden'); - } - - // 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); + Network.prototype._handleOnDrag = function(event) { + if (this.drag.pinched) { + return; } - }; - - /** - * Get the width of the group label - * @return {number} width - */ - Group.prototype.getLabelWidth = function() { - return this.props.label.width; - }; + var pointer = this._getPointer(event.gesture.center); - /** - * 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; + 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; - this.visibleItems = this._updateVisibleItems(this.orderedItems, this.visibleItems, range); + // update position of all selected nodes + selection.forEach(function (s) { + var node = s.node; - // 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; + if (!s.xFixed) { + node.x = me._XconvertDOMtoCanvas(me._XconvertCanvasToDOM(s.x) + deltaX); + } - util.forEach(this.items, function (item) { - item.dirty = true; - if (item.displayed) item.redraw(); + if (!s.yFixed) { + node.y = me._YconvertDOMtoCanvas(me._YconvertCanvasToDOM(s.y) + deltaY); + } }); - restack = true; - } - - // 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); - } - // 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; - }); + // start _animationStep if not yet running + if (!this.moving) { + this.moving = true; + this.start(); } - height = max + margin.item.vertical / 2; } else { - height = margin.axis + margin.item.vertical; - } - 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'; + if (this.constants.dragNetwork == true) { + // move the network + var diffX = pointer.x - this.drag.pointer.x; + var diffY = pointer.y - this.drag.pointer.y; - // 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(); + this._setTranslation( + this.drag.translation.x + diffX, + this.drag.translation.y + diffY + ); + this._redraw(); + // this.moving = true; + // this.start(); + } } - - return resized; }; /** - * Show this group: attach to the DOM + * handle drag start event + * @private */ - Group.prototype.show = function() { - if (!this.dom.label.parentNode) { - this.itemSet.dom.labelSet.appendChild(this.dom.label); - } - - if (!this.dom.foreground.parentNode) { - this.itemSet.dom.foreground.appendChild(this.dom.foreground); + 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(); } - - if (!this.dom.background.parentNode) { - this.itemSet.dom.background.appendChild(this.dom.background); + else { + this._redraw(); } - if (!this.dom.axis.parentNode) { - this.itemSet.dom.axis.appendChild(this.dom.axis); - } }; /** - * Hide this group: remove from the DOM + * handle tap/click event: select/unselect a node + * @private */ - Group.prototype.hide = function() { - var label = this.dom.label; - if (label.parentNode) { - label.parentNode.removeChild(label); - } + Network.prototype._onTap = function (event) { + var pointer = this._getPointer(event.gesture.center); + this.pointerPosition = pointer; + this._handleTap(pointer); - var foreground = this.dom.foreground; - if (foreground.parentNode) { - foreground.parentNode.removeChild(foreground); - } + }; - var background = this.dom.background; - if (background.parentNode) { - background.parentNode.removeChild(background); - } - var axis = this.dom.axis; - if (axis.parentNode) { - axis.parentNode.removeChild(axis); - } + /** + * handle doubletap event + * @private + */ + Network.prototype._onDoubleTap = function (event) { + var pointer = this._getPointer(event.gesture.center); + this._handleDoubleTap(pointer); }; + /** - * Add an item to the group - * @param {Item} item + * handle long tap event: multi select nodes + * @private */ - Group.prototype.add = function(item) { - this.items[item.id] = item; - item.setParent(this); - - if (item instanceof ItemRange && 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); - } + Network.prototype._onHold = function (event) { + var pointer = this._getPointer(event.gesture.center); + this.pointerPosition = pointer; + this._handleOnHold(pointer); }; /** - * Remove an item from the group - * @param {Item} item + * handle the release of the screen + * + * @private */ - Group.prototype.remove = function(item) { - delete this.items[item.id]; - item.setParent(this.itemSet); - - // remove from visible items - var index = this.visibleItems.indexOf(item); - if (index != -1) this.visibleItems.splice(index, 1); - - // TODO: also remove from ordered items? + Network.prototype._onRelease = function (event) { + var pointer = this._getPointer(event.gesture.center); + this._handleOnRelease(pointer); }; /** - * Remove an item from the corresponding DataSet - * @param {Item} item + * Handle pinch event + * @param event + * @private */ - Group.prototype.removeFromDataSet = function(item) { - this.itemSet.removeItem(item.id); + 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; + } + + // TODO: enabled moving while pinching? + var scale = this.pinch.scale * event.gesture.scale; + this._zoom(scale, pointer) }; /** - * Reorder the items + * 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 */ - Group.prototype.order = function() { - var array = util.toArray(this.items); - this.orderedItems.byStart = array; - this.orderedItems.byEnd = this._constructByEndArray(array); + 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; + } - stack.orderByStart(this.orderedItems.byStart); - stack.orderByEnd(this.orderedItems.byEnd); + 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(); + + 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._redraw(); + + if (scaleOld < scale) { + this.emit("zoom", {direction:"+"}); + } + else { + this.emit("zoom", {direction:"-"}); + } + + return scale; + } }; + /** - * Create an array containing all items being a range (having an end date) - * @param {Item[]} array - * @returns {ItemRange[]} + * 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._constructByEndArray = function(array) { - var endArray = []; + 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; + } - for (var i = 0; i < array.length; i++) { - if (array[i] instanceof ItemRange) { - endArray.push(array[i]); + // 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) { + + // calculate the new scale + var scale = this._getScale(); + var zoom = delta / 10; + if (delta < 0) { + zoom = zoom / (1 - zoom); } + scale *= (1 + zoom); + + // calculate the pointer location + var gesture = hammerUtil.fakeGesture(this, event); + var pointer = this._getPointer(gesture.center); + + // apply the new scale + this._zoom(scale, pointer); } - return endArray; + + // Prevent default actions caused by mouse wheel. + event.preventDefault(); }; + /** - * 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. + * Mouse move handler for checking whether the title moves over a node with a title. + * @param {Event} event * @private */ - Group.prototype._updateVisibleItems = function(orderedItems, visibleItems, range) { - var initialPosByStart, - newVisibleItems = [], - i; + Network.prototype._onMouseMoveTitle = function (event) { + var gesture = hammerUtil.fakeGesture(this, event); + var pointer = this._getPointer(gesture.center); - // 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); - } + // check if the previously selected node is still selected + if (this.popupObj) { + this._checkHidePopup(pointer); } - // 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'); + // 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 { - initialPosByStart = orderedItems.byStart.indexOf(newVisibleItems[0]); + if (!this.drag.dragging) { + this.popupTimer = setTimeout(checkShow, this.constants.tooltip.delay); } - // 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;} + /** + * 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]; + } } - } - // 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;} + // adding hover highlights + var obj = this._getNodeAt(pointer); + if (obj == null) { + obj = this._getEdgeAt(pointer); } - for (i = initialPosByEnd + 1; i < orderedItems.byEnd.length; i++) { - if (this._checkIfInvisible(orderedItems.byEnd[i], newVisibleItems, range)) {break;} + if (obj != null) { + this._hoverObject(obj); } - } - - return newVisibleItems; - }; - - - /** - * 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); + // 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]; + } + } } - return false; - } - else { - if (item.displayed) item.hide(); - return true; + this.redraw(); } }; /** - * 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. + * 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 {Item} item - * @param {Array} visibleItems - * @param {{start:number, end:number}} range + * @param {{x:Number, y:Number}} pointer * @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(); + 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; + } + } + } } - }; - module.exports = Group; + 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; + } + } + } + } + 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); + } -/***/ }, -/* 30 */ -/***/ function(module, exports, __webpack_require__) { + // 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(); + } + } + else { + if (this.popup) { + this.popup.hide(); + } + } + }; - // 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 + * 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 */ - exports.orderByStart = function(items) { - items.sort(function (a, b) { - return a.data.start - b.data.start; - }); + Network.prototype._checkHidePopup = function (pointer) { + if (!this.popupObj || !this._getNodeAt(pointer) ) { + this.popupObj = undefined; + if (this.popup) { + this.popup.hide(); + } + } }; + /** - * Order items by their end date. If they have no end date, their start date - * is used. - * @param {Item[]} items + * 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%') */ - 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.setSize = function(width, height) { + this.frame.style.width = width; + this.frame.style.height = height; - return aTime - bTime; - }); + 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; + + 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}); }; /** - * 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 + * Set a data set with nodes for the network + * @param {Array | DataSet | DataView} nodes The data containing the nodes. + * @private */ - exports.stack = function(items, margin, force) { - var i, iMax; + Network.prototype._setNodes = function(nodes) { + var oldNodesData = this.nodesData; - if (force) { - // reset top position of all items - for (i = 0, iMax = items.length; i < iMax; i++) { - items[i].top = null; - } + 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'); } - // 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; + if (oldNodesData) { + // unsubscribe from old dataset + util.forEach(this.nodesListeners, function (callback, event) { + oldNodesData.off(event, callback); + }); + } - 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; - } - } + // remove drawn nodes + this.nodes = {}; - 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); - } + if (this.nodesData) { + // subscribe to new dataset + var me = this; + util.forEach(this.nodesListeners, function (callback, event) { + me.nodesData.on(event, callback); + }); + + // draw all new nodes + var ids = this.nodesData.getIds(); + this._addNodes(ids); } + this._updateSelection(); }; /** - * 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. + * Add nodes + * @param {Number[] | String[]} ids + * @private */ - exports.nostack = function(items, margin) { - var i, iMax; + 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 - // reset top position of all items - for (i = 0, iMax = items.length; i < iMax; i++) { - items[i].top = margin.axis; + 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);} + } + 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(); }; /** - * 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 + * Update existing nodes, or create them when not yet existing + * @param {Number[] | String[]} ids + * @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); - }; - - -/***/ }, -/* 31 */ -/***/ function(module, exports, __webpack_require__) { - - 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); + 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); } - if (data.end == undefined) { - throw new Error('Property "end" missing in item ' + data.id); + else { + // create node + node = new Node(properties, this.images, this.groups, this.constants); + nodes[id] = node; } } - - Item.call(this, data, conversion, options); - } - - ItemRange.prototype = new Item (null, null, null); - - ItemRange.prototype.baseClassName = 'item range'; + this.moving = true; + if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { + this._resetLevels(); + this._setupHierarchicalLayout(); + } + this._updateNodeIndexList(); + this._reconnectEdges(); + this._updateValueRange(nodes); + }; /** - * 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 + * Remove existing nodes. If nodes do not exist, the method will just ignore it. + * @param {Number[] | String[]} ids + * @private */ - ItemRange.prototype.isVisible = function(range) { - // determine visibility - return (this.data.start < range.end) && (this.data.end > range.start); + 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); }; /** - * Repaint the item + * Load edges by reading the data table + * @param {Array | DataSet | DataView} edges The data containing the edges. + * @private + * @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; - } + Network.prototype._setEdges = function(edges) { + var oldEdgesData = this.edgesData; - // append DOM to parent DOM - if (!this.parent) { - throw new Error('Cannot redraw item: no parent attached'); + if (edges instanceof DataSet || edges instanceof DataView) { + this.edgesData = edges; } - 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); + else if (edges instanceof Array) { + this.edgesData = new DataSet(); + this.edgesData.add(edges); } - 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; + else if (!edges) { + this.edgesData = new DataSet(); } - - // update title - if (this.data.title != this.title) { - dom.box.title = this.data.title; - this.title = this.data.title; + else { + throw new TypeError('Array or DataSet expected'); } - // 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 (oldEdgesData) { + // unsubscribe from old dataset + util.forEach(this.edgesListeners, function (callback, event) { + oldEdgesData.off(event, callback); + }); } - // recalculate size - if (this.dirty) { - // determine from css whether this box has overflow - this.overflow = window.getComputedStyle(dom.content).overflow !== 'hidden'; + // remove drawn edges + this.edges = {}; - this.props.content.width = this.dom.content.offsetWidth; - this.height = this.dom.box.offsetHeight; + if (this.edgesData) { + // subscribe to new dataset + var me = this; + util.forEach(this.edgesListeners, function (callback, event) { + me.edgesData.on(event, callback); + }); - this.dirty = false; + // draw all new nodes + var ids = this.edgesData.getIds(); + this._addEdges(ids); } - this._repaintDeleteButton(dom.box); - this._repaintDragLeft(); - this._repaintDragRight(); + this._reconnectEdges(); }; /** - * Show the item in the DOM (when not already visible). The items DOM will - * be created when needed. + * Add edges + * @param {Number[] | String[]} ids + * @private */ - ItemRange.prototype.show = function() { - if (!this.displayed) { - this.redraw(); - } - }; + Network.prototype._addEdges = function (ids) { + var edges = this.edges, + edgesData = this.edgesData; - /** - * Hide the item from the DOM (when visible) - * @return {Boolean} changed - */ - ItemRange.prototype.hide = function() { - if (this.displayed) { - var box = this.dom.box; + for (var i = 0, len = ids.length; i < len; i++) { + var id = ids[i]; - if (box.parentNode) { - box.parentNode.removeChild(box); + var oldEdge = edges[id]; + if (oldEdge) { + oldEdge.disconnect(); } - this.top = null; - this.left = null; + var data = edgesData.get(id, {"showInternalIds" : true}); + edges[id] = new Edge(data, this, this.constants); + } - this.displayed = false; + this.moving = true; + this._updateValueRange(edges); + this._createBezierNodes(); + if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { + this._resetLevels(); + this._setupHierarchicalLayout(); } + this._updateCalculationNodes(); }; /** - * Reposition the item horizontally - * @Override + * Update existing edges, or create them when not yet existing + * @param {Number[] | String[]} ids + * @private */ - // TODO: delete the old function - 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; + 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]; - // 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 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; + } } - 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; + this._createBezierNodes(); + if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { + this._resetLevels(); + this._setupHierarchicalLayout(); } - 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.moving = true; + this._updateValueRange(edges); + }; - this.left = start; - this.width = boxWidth; + /** + * 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]; + } } - this.dom.box.style.left = this.left + 'px'; - this.dom.box.style.width = boxWidth + 'px'; - this.dom.content.style.left = contentLeft + 'px'; + this.moving = true; + this._updateValueRange(edges); + if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { + this._resetLevels(); + this._setupHierarchicalLayout(); + } + this._updateCalculationNodes(); }; /** - * Reposition the item vertically - * @Override + * Reconnect all edges + * @private */ - ItemRange.prototype.repositionY = function() { - var orientation = this.options.orientation, - box = this.dom.box; - - if (orientation == 'top') { - box.style.top = this.top + 'px'; + Network.prototype._reconnectEdges = function() { + var id, + nodes = this.nodes, + edges = this.edges; + for (id in nodes) { + if (nodes.hasOwnProperty(id)) { + nodes[id].edges = []; + } } - else { - box.style.top = (this.parent.height - this.top - this.height) + 'px'; + + for (id in edges) { + if (edges.hasOwnProperty(id)) { + var edge = edges[id]; + edge.from = null; + edge.to = null; + edge.connect(); + } } }; /** - * Repaint a drag area on the left side of the range when the range is selected - * @protected + * 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 */ - 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') - }); + Network.prototype._updateValueRange = function(obj) { + var id; - this.dom.box.appendChild(dragLeft); - this.dom.dragLeft = dragLeft; + // 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); + } + } } - else if (!this.selected && this.dom.dragLeft) { - // delete drag area - if (this.dom.dragLeft.parentNode) { - this.dom.dragLeft.parentNode.removeChild(this.dom.dragLeft); + + // adjust the range of all objects + if (valueMin !== undefined && valueMax !== undefined) { + for (id in obj) { + if (obj.hasOwnProperty(id)) { + obj[id].setValueRange(valueMin, valueMax); + } } - this.dom.dragLeft = null; } }; /** - * Repaint a drag area on the right side of the range when the range is selected - * @protected + * Redraw the network with the current data + * chart will be resized too. */ - 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; + Network.prototype.redraw = function() { + this.setSize(this.width, this.height); + this._redraw(); + }; - // TODO: this should be redundant? - Hammer(dragRight, { - preventDefault: true - }).on('drag', function () { - //console.log('drag right') - }); + /** + * 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); - 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; + // 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) + }; + + + this._doInAllSectors("_drawAllSectorNodes",ctx); + if (this.drag.dragging == false || this.drag.dragging === undefined || this.constants.hideEdgesOnDrag == false) { + this._doInAllSectors("_drawEdges",ctx); } - }; - module.exports = ItemRange; + if (this.drag.dragging == false || this.drag.dragging === undefined || this.constants.hideNodesOnDrag == false) { + this._doInAllSectors("_drawNodes",ctx,false); + } + if (this.controlNodesActive == true) { + this._doInAllSectors("_drawControlNodes",ctx); + } -/***/ }, -/* 32 */ -/***/ function(module, exports, __webpack_require__) { + // this._doInSupportSector("_drawNodes",ctx,true); + // this._drawTree(ctx,"#F00F0F"); - var Hammer = __webpack_require__(18); + // restore original scaling and translation + ctx.restore(); + }; /** - * @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 + * Set the translation of the network + * @param {Number} offsetX Horizontal offset + * @param {Number} offsetY Vertical offset + * @private */ - function Item (data, conversion, options) { - this.id = null; - this.parent = null; - this.data = data; - this.dom = null; - this.conversion = conversion || {}; - this.options = options || {}; + Network.prototype._setTranslation = function(offsetX, offsetY) { + if (this.translation === undefined) { + this.translation = { + x: 0, + y: 0 + }; + } - this.selected = false; - this.displayed = false; - this.dirty = true; + if (offsetX !== undefined) { + this.translation.x = offsetX; + } + if (offsetY !== undefined) { + this.translation.y = offsetY; + } - this.top = null; - this.left = null; - this.width = null; - this.height = null; - } + this.emit('viewChanged'); + }; /** - * Select current item + * Get the translation of the network + * @return {Object} translation An object with parameters x and y, both a number + * @private */ - Item.prototype.select = function() { - this.selected = true; - if (this.displayed) this.redraw(); + Network.prototype._getTranslation = function() { + return { + x: this.translation.x, + y: this.translation.y + }; }; /** - * Unselect current item + * Scale the network + * @param {Number} scale Scaling factor 1.0 is unscaled + * @private */ - Item.prototype.unselect = function() { - this.selected = false; - if (this.displayed) this.redraw(); + Network.prototype._setScale = function(scale) { + this.scale = scale; }; /** - * Set a parent for the item - * @param {ItemSet | Group} parent + * Get the current scale of the network + * @return {Number} scale Scaling factor 1.0 is unscaled + * @private */ - Item.prototype.setParent = function(parent) { - if (this.displayed) { - this.hide(); - this.parent = parent; - if (this.parent) { - this.show(); - } - } - else { - this.parent = parent; - } + Network.prototype._getScale = function() { + return this.scale; }; /** - * 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 + * 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 */ - Item.prototype.isVisible = function(range) { - // Should be implemented by Item implementations - return false; + Network.prototype._XconvertDOMtoCanvas = function(x) { + return (x - this.translation.x) / this.scale; }; /** - * Show the Item in the DOM (when not already visible) - * @return {Boolean} changed + * 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 */ - Item.prototype.show = function() { - return false; + Network.prototype._XconvertCanvasToDOM = function(x) { + return x * this.scale + this.translation.x; }; /** - * Hide the Item from the DOM (when visible) - * @return {Boolean} changed + * 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 */ - Item.prototype.hide = function() { - return false; + Network.prototype._YconvertDOMtoCanvas = function(y) { + return (y - this.translation.y) / this.scale; }; /** - * Repaint the item + * 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 */ - Item.prototype.redraw = function() { - // should be implemented by the item + Network.prototype._YconvertCanvasToDOM = function(y) { + return y * this.scale + this.translation.y ; }; + /** - * Reposition the Item horizontally + * + * @param {object} pos = {x: number, y: number} + * @returns {{x: number, y: number}} + * @constructor */ - Item.prototype.repositionX = function() { - // should be implemented by the item - }; + Network.prototype.canvasToDOM = function(pos) { + return {x:this._XconvertCanvasToDOM(pos.x),y:this._YconvertCanvasToDOM(pos.y)}; + } /** - * Reposition the Item vertically + * + * @param {object} pos = {x: number, y: number} + * @returns {{x: number, y: number}} + * @constructor */ - Item.prototype.repositionY = function() { - // should be implemented by the item - }; + Network.prototype.DOMtoCanvas = function(pos) { + return {x:this._XconvertDOMtoCanvas(pos.x),y:this._YconvertDOMtoCanvas(pos.y)}; + } /** - * Repaint a delete button on the top right of the item when the item is selected - * @param {HTMLElement} anchor - * @protected + * 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._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'; + Network.prototype._drawNodes = function(ctx,alwaysShow) { + if (alwaysShow === undefined) { + alwaysShow = false; + } - Hammer(deleteButton, { - preventDefault: true - }).on('tap', function (event) { - me.parent.removeFromDataSet(me); - event.stopPropagation(); - }); + // first draw the unselected nodes + var nodes = this.nodes; + var selected = []; - anchor.appendChild(deleteButton); - this.dom.deleteButton = deleteButton; + 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 if (!this.selected && this.dom.deleteButton) { - // remove button - if (this.dom.deleteButton.parentNode) { - this.dom.deleteButton.parentNode.removeChild(this.dom.deleteButton); + + // 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); } - this.dom.deleteButton = null; } }; - 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 + * Redraw all edges + * The 2d context of a HTML canvas can be retrieved by canvas.getContext('2d'); + * @param {CanvasRenderingContext2D} ctx + * @private */ - function ItemBox (data, conversion, options) { - this.props = { - dot: { - width: 0, - height: 0 - }, - line: { - width: 0, - height: 0 + 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); + } } - }; + } + }; - // validate data - if (data) { - if (data.start == undefined) { - throw new Error('Property "start" missing in item ' + data); + /** + * 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); } } + }; - Item.call(this, data, conversion, options); - } + /** + * Find a stable position for all nodes + * @private + */ + Network.prototype._stabilize = function() { + if (this.constants.freezeForStabilization == true) { + this._freezeDefinedNodes(); + } - ItemBox.prototype = new Item (null, null, null); + // 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}); + }; /** - * 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 + * 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 */ - 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._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; + } + } + } }; /** - * Repaint the item + * Unfreezes the nodes that have been frozen by _freezeDefinedNodes. + * + * @private */ - ItemBox.prototype.redraw = function() { - var dom = this.dom; - if (!dom) { - // create DOM - this.dom = {}; - dom = this.dom; - - // create main box - dom.box = document.createElement('DIV'); - - // contents box (inside the background box). used for making margins - dom.content = document.createElement('DIV'); - dom.content.className = 'content'; - dom.box.appendChild(dom.content); - - // line to axis - dom.line = document.createElement('DIV'); - dom.line.className = 'line'; - - // dot on axis - dom.dot = document.createElement('DIV'); - dom.dot.className = 'dot'; - - // attach this item as attribute - dom.box['timeline-item'] = this; + 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; + } + } } + }; - // 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; - // 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); + /** + * 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; } - - this.dirty = true; } + return false; + }; - // 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; + /** + * /** + * 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; - this.dirty = true; + 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; + } + } } - // 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; + 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; - this.dirty = false; + } } - - this._repaintDeleteButton(dom.box); }; /** - * Show the item in the DOM (when not already displayed). The items DOM will - * be created when needed. + * A single simulation step (or "tick") in the physics simulation + * + * @private */ - ItemBox.prototype.show = function() { - if (!this.displayed) { - this.redraw(); + 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()) + } } }; + /** - * Hide the item from the DOM (when visible) + * 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.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._animationStep = function() { + // reset the timer so a new scheduled animation step can be set + this.timer = undefined; + // handle the keyboad movement + this._handleNavigation(); - this.top = null; - this.left = null; + // this schedules a new animation step + this.start(); - this.displayed = false; + // 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; + }; + if (typeof window !== 'undefined') { + window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || + window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; + } + /** - * Reposition the item horizontally - * @Override + * Schedule a animation step with the refreshrate interval. */ - 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; + 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(); - // calculate left position of the box - if (align == 'right') { - this.left = start - this.width; - } - else if (align == 'left') { - this.left = start; + 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; + } + } + + 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 { - // default or 'center' - this.left = start - this.width / 2; + this._redraw(); } - - // 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'; }; + /** - * Reposition the item vertically - * @Override + * Move the network according to the keyboard presses. + * + * @private */ - ItemBox.prototype.repositionY = function() { - var orientation = this.options.orientation, - box = this.dom.box, - line = this.dom.line, - dot = this.dom.dot; - - if (orientation == 'top') { - box.style.top = (this.top || 0) + 'px'; - - line.style.top = '0'; - line.style.height = (this.parent.top + this.top + 1) + 'px'; - line.style.bottom = ''; + 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); } - 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; - - box.style.top = (this.parent.height - this.top - this.height || 0) + 'px'; - line.style.top = (itemSetHeight - lineHeight) + 'px'; - line.style.bottom = '0'; + 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); } - - dot.style.top = (-this.props.dot.height / 2) + 'px'; }; - module.exports = ItemBox; - - -/***/ }, -/* 34 */ -/***/ function(module, exports, __webpack_require__) { - - var Item = __webpack_require__(32); /** - * @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 + * Freeze the _animationStep */ - 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); - } + Network.prototype.toggleFreeze = function() { + if (this.freezeSimulation == false) { + this.freezeSimulation = true; + } + else { + this.freezeSimulation = false; + this.start(); } - - Item.call(this, data, conversion, options); - } - - 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); }; + /** - * Repaint the item + * This function cleans the support nodes if they are not needed and adds them when they are. + * + * @param {boolean} [disableStart] + * @private */ - ItemPoint.prototype.redraw = function() { - var dom = this.dom; - if (!dom) { - // create DOM - this.dom = {}; - dom = this.dom; - - // background box - dom.point = document.createElement('div'); - // className is updated in redraw() - - // contents box, right from the dot - dom.content = document.createElement('div'); - dom.content.className = 'content'; - dom.point.appendChild(dom.content); - - // dot at start - dom.dot = document.createElement('div'); - dom.point.appendChild(dom.dot); - - // attach this item as attribute - dom.point['timeline-item'] = this; - } - - // append DOM to parent DOM - if (!this.parent) { - throw new Error('Cannot redraw item: no parent attached'); + Network.prototype._configureSmoothCurves = function(disableStart) { + if (disableStart === undefined) { + disableStart = true; } - 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'); + 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]] === undefined) { + delete this.sectors['support']['nodes'][nodeId]; + } + } } - foreground.appendChild(dom.point); } - 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); + else { + // delete the support nodes + this.sectors['support']['nodes'] = {}; + for (var edgeId in this.edges) { + if (this.edges.hasOwnProperty(edgeId)) { + this.edges[edgeId].smooth = false; + this.edges[edgeId].via = null; + } } - - this.dirty = true; - } - - // update title - if (this.data.title != this.title) { - dom.point.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.point.className = 'item point' + className; - dom.dot.className = 'item dot' + className; - - this.dirty = true; } - // 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; - - // resize contents - dom.content.style.marginLeft = 2 * this.props.dot.width + 'px'; - //dom.content.style.marginRight = ... + 'px'; // TODO: margin right - - dom.dot.style.top = ((this.height - this.props.dot.height) / 2) + 'px'; - dom.dot.style.left = (this.props.dot.width / 2) + 'px'; - this.dirty = false; + this._updateCalculationNodes(); + if (!disableStart) { + this.moving = true; + this.start(); } - - this._repaintDeleteButton(dom.point); }; + /** - * Show the item in the DOM (when not already visible). The items DOM will - * be created when needed. + * 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 */ - ItemPoint.prototype.show = function() { - if (!this.displayed) { - this.redraw(); + 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) { + edge.smooth = true; + 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(); + } + } + } } }; /** - * Hide the item from the DOM (when visible) + * load the functions that load the mixins into the prototype. + * + * @private */ - ItemPoint.prototype.hide = function() { - if (this.displayed) { - if (this.dom.point.parentNode) { - this.dom.point.parentNode.removeChild(this.dom.point); + Network.prototype._initializeMixinLoaders = function () { + for (var mixin in MixinLoader) { + if (MixinLoader.hasOwnProperty(mixin)) { + Network.prototype[mixin] = MixinLoader[mixin]; } - - this.top = null; - this.left = null; - - this.displayed = false; } }; /** - * Reposition the item horizontally - * @Override + * Load the XY positions of the nodes into the dataset. */ - ItemPoint.prototype.repositionX = function() { - var start = this.conversion.toScreen(this.data.start); - - this.left = start - this.props.dot.width; - - // reposition point - this.dom.point.style.left = this.left + 'px'; + 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] */ - ItemPoint.prototype.repositionY = function() { - var orientation = this.options.orientation, - point = this.dom.point; + 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') { - point.style.top = this.top + 'px'; + var requiredScale = zoomLevel; + this._setScale(requiredScale); + + var canvasCenter = this.DOMtoCanvas({x:0.5 * this.frame.canvas.width,y:0.5 * this.frame.canvas.height}); + var translation = this._getTranslation(); + + var distanceFromCenter = {x:canvasCenter.x - nodePosition.x, + y:canvasCenter.y - nodePosition.y}; + + this._setTranslation(translation.x + requiredScale * distanceFromCenter.x, + translation.y + requiredScale * distanceFromCenter.y); + this.redraw(); } else { - point.style.top = (this.parent.height - this.top - this.height) + 'px'; + console.log("This nodeId cannot be found.") } }; - module.exports = ItemPoint; + module.exports = Network; /***/ }, -/* 35 */ +/* 33 */ /***/ function(module, exports, __webpack_require__) { - var Emitter = __webpack_require__(10); - var Hammer = __webpack_require__(18); var util = __webpack_require__(1); +<<<<<<< HEAD var DataSet = __webpack_require__(7); var DataView = __webpack_require__(8); var Range = __webpack_require__(20); @@ -16687,215 +15707,207 @@ return /******/ (function(modules) { // webpackBootstrap var CurrentTime = __webpack_require__(26); var CustomTime = __webpack_require__(27); var LineGraph = __webpack_require__(36); +======= + var Node = __webpack_require__(36); +>>>>>>> b6ed63dda6f296069050476eabc9b3a9e165069f /** - * 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 + * @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 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]; - } + function Edge (properties, network, constants) { + if (!network) { + throw "No network provided"; } + this.network = network; - var me = this; - this.defaultOptions = { - start: null, - end: null, + // initialize constants + this.widthMin = constants.edges.widthMin; + this.widthMax = constants.edges.widthMax; - autoResize: true, + // initialize variables + this.id = undefined; + this.fromId = undefined; + this.toId = undefined; + this.style = constants.edges.style; + this.title = undefined; + this.width = constants.edges.width; + this.widthSelectionMultiplier = constants.edges.widthSelectionMultiplier; + this.widthSelected = this.width * this.widthSelectionMultiplier; + this.hoverWidth = constants.edges.hoverWidth; + this.value = undefined; + this.length = constants.physics.springLength; + this.customLength = false; + this.selected = false; + this.hover = false; + this.smoothCurves = constants.smoothCurves; + this.dynamicSmoothCurves = constants.dynamicSmoothCurves; + this.arrowScaleFactor = constants.edges.arrowScaleFactor; + this.inheritColor = constants.edges.inheritColor; - orientation: 'bottom', - width: null, - height: null, - maxHeight: null, - minHeight: null - }; - this.options = util.deepExtend({}, this.defaultOptions); + this.from = null; // a node + this.to = null; // a node + this.via = null; // a temp node - // Create the DOM, props, and emitter - this._create(container); + // 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 = []; - // all components listed here will be repainted automatically - this.components = []; + this.connected = false; - 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) - } - }; + // Added to support dashed lines + // David Jordan + // 2012-08-08 + this.dash = util.extend({}, constants.edges.dash); // contains properties length, gap, altLength - // range - this.range = new Range(this.body); - this.components.push(this.range); - this.body.range = this.range; + this.color = {color:constants.edges.color.color, + highlight:constants.edges.color.highlight, + hover:constants.edges.color.hover}; + this.widthFixed = false; + this.lengthFixed = false; - // time axis - this.timeAxis = new TimeAxis(this.body); - this.components.push(this.timeAxis); - this.body.util.snap = this.timeAxis.snap.bind(this.timeAxis); + this.setProperties(properties, constants); - // current time bar - this.currentTime = new CurrentTime(this.body); - this.components.push(this.currentTime); + this.controlNodesEnabled = false; + this.controlNodes = {from:null, to:null, positions:{}}; + this.connectedNode = null; + } - // 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); + /** + * 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, constants) { + if (!properties) { + return; + } - // item set - this.linegraph = new LineGraph(this.body); - this.components.push(this.linegraph); + if (properties.from !== undefined) {this.fromId = properties.from;} + if (properties.to !== undefined) {this.toId = properties.to;} - this.itemsData = null; // DataSet - this.groupsData = null; // DataSet + if (properties.id !== undefined) {this.id = properties.id;} + if (properties.style !== undefined) {this.style = properties.style;} + if (properties.label !== undefined) {this.label = properties.label;} - // apply options - if (options) { - this.setOptions(options); - } + if (this.label) { + this.fontSize = constants.edges.fontSize; + this.fontFace = constants.edges.fontFace; + this.fontColor = constants.edges.fontColor; + this.fontFill = constants.edges.fontFill; - // IMPORTANT: THIS HAPPENS BEFORE SET ITEMS! - if (groups) { - this.setGroups(groups); + if (properties.fontColor !== undefined) {this.fontColor = properties.fontColor;} + if (properties.fontSize !== undefined) {this.fontSize = properties.fontSize;} + if (properties.fontFace !== undefined) {this.fontFace = properties.fontFace;} + if (properties.fontFill !== undefined) {this.fontFill = properties.fontFill;} } - // create itemset - if (items) { - this.setItems(items); + if (properties.title !== undefined) {this.title = properties.title;} + if (properties.width !== undefined) {this.width = properties.width;} + if (properties.widthSelectionMultiplier !== undefined) + {this.widthSelectionMultiplier = properties.widthSelectionMultiplier;} + if (properties.hoverWidth !== undefined) {this.hoverWidth = properties.hoverWidth;} + if (properties.value !== undefined) {this.value = properties.value;} + if (properties.length !== undefined) {this.length = properties.length; + this.customLength = true;} + + // scale the arrow + if (properties.arrowScaleFactor !== undefined) {this.arrowScaleFactor = properties.arrowScaleFactor;} + + if (properties.inheritColor !== undefined) {this.inheritColor = properties.inheritColor;} + + // Added to support dashed lines + // David Jordan + // 2012-08-08 + if (properties.dash) { + if (properties.dash.length !== undefined) {this.dash.length = properties.dash.length;} + if (properties.dash.gap !== undefined) {this.dash.gap = properties.dash.gap;} + if (properties.dash.altLength !== undefined) {this.dash.altLength = properties.dash.altLength;} } - else { - this.redraw(); + + if (properties.color !== undefined) { + if (util.isString(properties.color)) { + this.color.color = properties.color; + this.color.highlight = properties.color; + } + else { + if (properties.color.color !== undefined) {this.color.color = properties.color.color;} + if (properties.color.highlight !== undefined) {this.color.highlight = properties.color.highlight;} + if (properties.color.hover !== undefined) {this.color.hover = properties.color.hover;} + } } - } - /** - * 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 - */ - 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); + // A node is connected when it has a from and to node. + this.connect(); - // enable/disable autoResize - this._initAutoResize(); - } + this.widthFixed = this.widthFixed || (properties.width !== undefined); + this.lengthFixed = this.lengthFixed || (properties.length !== undefined); - // propagate options to all components - this.components.forEach(function (component) { - component.setOptions(options); - }); + this.widthSelected = this.width * this.widthSelectionMultiplier; - // 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.'); + // set draw method based on style + switch (this.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; } - - // redraw everything - this.redraw(); }; - /** - * Set items - * @param {vis.DataSet | Array | google.visualization.DataTable | null} items + * Connect an edge to its nodes */ - Graph2d.prototype.setItems = function(items) { - var initialLoad = (this.itemsData == null); + Edge.prototype.connect = function () { + this.disconnect(); - // convert to type DataSet when needed - var newDataSet; - if (!items) { - newDataSet = null; - } - else if (items instanceof DataSet || items instanceof DataView) { - newDataSet = items; + 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 { - // 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.from) { + this.from.detachEdge(this); + } + if (this.to) { + this.to.detachEdge(this); + } } }; /** - * Set groups - * @param {vis.DataSet | Array | google.visualization.DataTable} groups + * Disconnect an edge from its nodes */ - Graph2d.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; + Edge.prototype.disconnect = function () { + if (this.from) { + this.from.detachEdge(this); + this.from = null; } - else { - // turn an array into a dataset - newDataSet = new DataSet(groups); + if (this.to) { + this.to.detachEdge(this); + this.to = null; } - this.groupsData = newDataSet; - this.linegraph.setGroups(newDataSet); + this.connected = false; }; +<<<<<<< HEAD /** * * @param groupId @@ -17034,12 +16046,23 @@ return /******/ (function(modules) { // webpackBootstrap me._onRemoveGroups(params.items); } }; +======= + /** + * get the title of this edge. + * @return {string} title The title of the edge, or undefined when no title + * has been set. + */ + Edge.prototype.getTitle = function() { + return typeof this.title === "function" ? this.title() : this.title; + }; +>>>>>>> b6ed63dda6f296069050476eabc9b3a9e165069f 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 +<<<<<<< HEAD this.svgElements = {}; this.setOptions(options); this.groupsUsingDefaultStyles = [0]; @@ -17158,89 +16181,243 @@ return /******/ (function(modules) { // webpackBootstrap // remove the frame containing the items if (this.dom.frame.parentNode) { this.dom.frame.parentNode.removeChild(this.dom.frame); - } +======= + /** + * Retrieve the value of the edge. Can be undefined + * @return {Number} value + */ + Edge.prototype.getValue = function() { + return this.value; }; /** - * Show the component in the DOM (when not already visible). - * @return {Boolean} changed + * Adjust the value range of the edge. The edge will adjust it's width + * based on its value. + * @param {Number} min + * @param {Number} max */ - LineGraph.prototype.show = function() { - // show frame containing the items - if (!this.dom.frame.parentNode) { - this.body.dom.center.appendChild(this.dom.frame); + Edge.prototype.setValueRange = function(min, max) { + if (!this.widthFixed && this.value !== undefined) { + var scale = (this.widthMax - this.widthMin) / (max - min); + this.width = (this.value - min) * scale + this.widthMin; + this.widthSelected = this.width * this.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 + */ + Edge.prototype.draw = function(ctx) { + throw "Method draw not initialized in edge"; + }; /** - * Set items - * @param {vis.DataSet | null} items + * 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 */ - LineGraph.prototype.setItems = function(items) { - var me = this, - ids, - oldItemsData = this.itemsData; + 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; - // replace the dataset - if (!items) { - this.itemsData = null; - } - else if (items instanceof DataSet || items instanceof DataView) { - this.itemsData = items; + var dist = this._getDistanceToEdge(xFrom, yFrom, xTo, yTo, xObj, yObj); + + return (dist < distMax); } else { - throw new TypeError('Data must be an instance of DataSet or DataView'); + return false } + }; - 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); + Edge.prototype._getColor = function() { + var colorObj = this.color; + if (this.inheritColor == "to") { + colorObj = { + highlight: this.to.color.highlight.border, + hover: this.to.color.hover.border, + color: this.to.color.border + }; + } + else if (this.inheritColor == "from" || this.inheritColor == true) { + colorObj = { + highlight: this.from.color.highlight.border, + hover: this.from.color.hover.border, + color: this.from.color.border + }; } - if (this.itemsData) { - // subscribe to new dataset - var id = this.id; - util.forEach(this.itemListeners, function (callback, event) { - me.itemsData.on(event, callback, id); - }); + if (this.selected == true) {return colorObj.highlight;} + else if (this.hover == true) {return colorObj.hover;} + else {return colorObj.color;} + } - // add all new items - ids = this.itemsData.getIds(); - this._onAdd(ids); - } - this._updateUngrouped(); - this._updateGraph(); - this.redraw(); - }; /** - * Set groups - * @param {vis.DataSet} groups + * 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 */ - LineGraph.prototype.setGroups = function(groups) { - var me = this, - ids; - - // unsubscribe from current dataset - if (this.groupsData) { - util.forEach(this.groupListeners, function (callback, event) { - me.groupsData.unsubscribe(event, callback); - }); + Edge.prototype._drawLine = function(ctx) { + // set style + ctx.strokeStyle = this._getColor(); + ctx.lineWidth = this._getLineWidth(); - // remove all drawn groups - ids = this.groupsData.getIds(); - this.groupsData = null; - this._onRemoveGroups(ids); // note: this will cause a redraw - } + if (this.from != this.to) { + // draw line + var via = this._line(ctx); - // replace the dataset + // draw label + var point; + if (this.label) { + if (this.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.length / 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); +>>>>>>> b6ed63dda6f296069050476eabc9b3a9e165069f + } + }; + + /** +<<<<<<< HEAD + * 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); +======= + * Get the line width of the edge. Depends on width and whether one of the + * connected nodes is selected. + * @return {Number} width + * @private + */ + Edge.prototype._getLineWidth = function() { + if (this.selected == true) { + return Math.min(this.widthSelected, this.widthMax)*this.networkScaleInv; + } + else { + if (this.hover == true) { + return Math.min(this.hoverWidth, this.widthMax)*this.networkScaleInv; + } + else { + return this.width*this.networkScaleInv; + } +>>>>>>> b6ed63dda6f296069050476eabc9b3a9e165069f + } + }; + + Edge.prototype._getViaCoordinates = function () { + var xVia = null; + var yVia = null; + var factor = this.smoothCurves.roundness; + var type = this.smoothCurves.type; + +<<<<<<< HEAD + /** + * Set items + * @param {vis.DataSet | null} items + */ + 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'); + } + + 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); + } + + if (this.itemsData) { + // subscribe to new dataset + var id = this.id; + util.forEach(this.itemListeners, function (callback, event) { + me.itemsData.on(event, callback, id); + }); + + // add all new items + ids = this.itemsData.getIds(); + this._onAdd(ids); + } + this._updateUngrouped(); + this._updateGraph(); + this.redraw(); + }; + + /** + * Set groups + * @param {vis.DataSet} groups + */ + LineGraph.prototype.setGroups = function(groups) { + var me = this, + ids; + + // 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; } @@ -17360,155 +16537,486 @@ return /******/ (function(modules) { // webpackBootstrap if (this.groups.hasOwnProperty(groupId)) { this.groups[groupId].setItems(groupsContent[groupId]); } +======= + 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; + } } - } - }; - - /** - * 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; - } + 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; + } } - - // 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); + } + 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; } - // console.log("getting amount ungrouped",new Date() - t1); - // console.log("putting in ungrouped",new Date() - t0); } - else { - delete this.groups[UNGROUPED]; - this.legendLeft.removeGroup(UNGROUPED); - this.legendRight.removeGroup(UNGROUPED); - this.yAxisLeft.removeGroup(UNGROUPED); - this.yAxisRight.removeGroup(UNGROUPED); + 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; + } + } + } + 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; + } + } + } } - this.legendLeft.redraw(); - this.legendRight.redraw(); - }; + return {x:xVia, y:yVia}; + } /** - * Redraw the component, mandatory function - * @return {boolean} Returns true if the component is resized + * Draw a line between two nodes + * @param {CanvasRenderingContext2D} ctx + * @private */ - LineGraph.prototype.redraw = function() { - var resized = false; - - this.svg.style.height = ('' + this.options.graphHeight).replace('px','') + 'px'; - if (this.lastWidth === undefined && this.width || this.lastWidth != this.width) { - resized = true; + Edge.prototype._line = function (ctx) { + // draw a straight line + ctx.beginPath(); + ctx.moveTo(this.from.x, this.from.y); + if (this.smoothCurves.enabled == true) { + if (this.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; + } } - // 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; + else { + ctx.lineTo(this.to.x, this.to.y); + ctx.stroke(); + return null; + } + }; - // calculate actual size and position - this.width = this.dom.frame.offsetWidth; + /** + * 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(); + }; - // 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); - } - if (zoomed == true) { - this._updateGraph(); - } + /** + * 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.fontSize + "px " + this.fontFace; + ctx.fillStyle = this.fontFill; + var width = ctx.measureText(text).width; + var height = this.fontSize; + var left = x - width / 2; + var top = y - height / 2; - this.legendLeft.redraw(); - this.legendRight.redraw(); + ctx.fillRect(left, top, width, height); - return resized; + // draw text + ctx.fillStyle = this.fontColor || "black"; + ctx.textAlign = "left"; + ctx.textBaseline = "top"; + ctx.fillText(text, left, top); + } }; /** - * Update and redraw the graph. - * + * 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 */ - LineGraph.prototype._updateGraph = function () { - // reset the svg elements - DOMutil.prepareElements(this.svgElements); + Edge.prototype._drawDashLine = function(ctx) { + // set style + if (this.selected == true) {ctx.strokeStyle = this.color.highlight;} + else if (this.hover == true) {ctx.strokeStyle = this.color.hover;} + else {ctx.strokeStyle = this.color.color;} - if (this.width != 0 && this.itemsData != null) { - var group, groupData, preprocessedGroup, i; - var preprocessedGroupData = []; - var processedGroupData = []; - var groupRanges = []; - var changeCalled = false; + ctx.lineWidth = this._getLineWidth(); - // getting group Ids - var groupIds = []; - for (var groupId in this.groups) { - if (this.groups.hasOwnProperty(groupId)) { - groupIds.push(groupId); - } + 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.dash.length !== undefined && this.dash.gap !== undefined) { + pattern = [this.dash.length,this.dash.gap]; + } + else { + pattern = [5,5]; } - // 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); + // set dash settings for chrome or firefox + if (typeof ctx.setLineDash !== 'undefined') { //Chrome + ctx.setLineDash(pattern); + ctx.lineDashOffset = 0; - // 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')); + } else { //Firefox + ctx.mozDash = pattern; + ctx.mozDashOffset = 0; + } + + // draw the line + via = this._line(ctx); + + // restore the dash settings. + if (typeof ctx.setLineDash !== 'undefined') { //Chrome + ctx.setLineDash([0]); + ctx.lineDashOffset = 0; + + } else { //Firefox + ctx.mozDash = [0]; + ctx.mozDashOffset = 0; + } + } + else { // unsupporting smooth lines + // draw dashed line + ctx.beginPath(); + ctx.lineCap = 'round'; + if (this.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.dash.length,this.dash.gap,this.dash.altLength,this.dash.gap]); + } + else if (this.dash.length !== undefined && this.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.dash.length,this.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); +>>>>>>> b6ed63dda6f296069050476eabc9b3a9e165069f + } + ctx.stroke(); + } +<<<<<<< HEAD + }; + + /** + * 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; + } + } + } + } + + // 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); + } + else { + delete this.groups[UNGROUPED]; + this.legendLeft.removeGroup(UNGROUPED); + this.legendRight.removeGroup(UNGROUPED); + this.yAxisLeft.removeGroup(UNGROUPED); + this.yAxisRight.removeGroup(UNGROUPED); +======= + + // draw label + if (this.label) { + var point; + if (this.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); +>>>>>>> b6ed63dda6f296069050476eabc9b3a9e165069f + } + + this.legendLeft.redraw(); + this.legendRight.redraw(); + }; + + + /** +<<<<<<< HEAD + * Redraw the component, mandatory function + * @return {boolean} Returns true if the component is resized + */ + LineGraph.prototype.redraw = function() { + var resized = false; + + 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; + + // 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); + } + if (zoomed == true) { + this._updateGraph(); + } + + this.legendLeft.redraw(); + this.legendRight.redraw(); + + return resized; + }; + + /** + * Update and redraw the graph. + * + */ + LineGraph.prototype._updateGraph = function () { + // reset the svg elements + DOMutil.prepareElements(this.svgElements); + + if (this.width != 0 && this.itemsData != null) { + var group, groupData, preprocessedGroup, i; + var preprocessedGroupData = []; + var processedGroupData = []; + var groupRanges = []; + var changeCalled = false; + + // getting group Ids + var groupIds = []; + for (var groupId in this.groups) { + if (this.groups.hasOwnProperty(groupId)) { + groupIds.push(groupId); + } + } + + // 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); + + // 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]; @@ -17676,9181 +17184,10794 @@ return /******/ (function(modules) { // webpackBootstrap } return changed; }; - +======= + * 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 + } + }; /** - * draw a bar graph - * @param datapoints - * @param group + * 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._drawBarGraph = function (dataset, group) { - if (dataset != null) { - if (dataset.length > 0) { - var coreDistance; - var minWidth = 0.1 * group.options.barChart.width; - var offset = 0; - var width = group.options.barChart.width; - - if (group.options.barChart.align == 'left') {offset -= 0.5*width;} - else if (group.options.barChart.align == 'right') {offset += 0.5*width;} - - for (var i = 0; i < dataset.length; i++) { - // dynammically downscale the width so there is no overlap up to 1/10th the original width - 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 < width) {width = coreDistance < minWidth ? minWidth : coreDistance;} - - DOMutil.drawBar(dataset[i].x + offset, dataset[i].y, width, group.zeroPosition - dataset[i].y, group.className + ' bar', this.svgElements, this.svg); - } - - // draw points - if (group.options.drawPoints.enabled == true) { - this._drawPoints(dataset, group, this.svgElements, this.svg, offset); - } - } + 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) } }; - /** - * draw a line graph - * - * @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); - } - - // 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); - } - } - } - }; - - /** - * 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 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} + * 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._preprocessData = function (datapoints, group) { - var extractedData = []; - var xValue, yValue; - var toScreen = this.body.util.toScreen; + Edge.prototype._drawArrowCenter = function(ctx) { + var point; + // set style + if (this.selected == true) {ctx.strokeStyle = this.color.highlight; ctx.fillStyle = this.color.highlight;} + else if (this.hover == true) {ctx.strokeStyle = this.color.hover; ctx.fillStyle = this.color.hover;} + else {ctx.strokeStyle = this.color.color; ctx.fillStyle = this.color.color;} + ctx.lineWidth = this._getLineWidth(); - var increment = 1; - var amountOfPoints = datapoints.length; + if (this.from != this.to) { + // draw line + var via = this._line(ctx); - var yMin = datapoints[0].y; - var yMax = datapoints[0].y; + var angle = Math.atan2((this.to.y - this.from.y), (this.to.x - this.from.x)); + var length = (10 + 5 * this.width) * this.arrowScaleFactor; + // draw an arrow halfway the line + if (this.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); + } - // 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))); - } + ctx.arrow(point.x, point.y, angle, length); + ctx.fill(); + ctx.stroke(); - 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; + // 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.length); + 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); - // extractedData.sort(function (a,b) {return a.x - b.x;}); - return {min: yMin, max: yMax, data: extractedData}; - }; - - /** - * 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 - */ - LineGraph.prototype._convertYvalues = function (datapoints, group) { - var extractedData = []; - var xValue, yValue; - var axis = this.yAxisLeft; - var svgHeight = Number(this.svg.style.height.replace("px","")); - - if (group.options.yAxisOrientation == 'right') { - axis = this.yAxisRight; - } + // draw all arrows + var angle = 0.2 * Math.PI; + var length = (10 + 5 * this.width) * this.arrowScaleFactor; + point = this._pointOnCircle(x, y, radius, 0.5); + ctx.arrow(point.x, point.y, angle, length); + ctx.fill(); + ctx.stroke(); - 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}); + // draw label + if (this.label) { + point = this._pointOnCircle(x, y, radius, 0.5); + this._label(ctx, this.label, point.x, point.y); + } } - - group.setZeroPosition(Math.min(svgHeight, axis.convertValue(0))); - - // extractedData.sort(function (a,b) {return a.x - b.x;}); - return extractedData; }; + /** - * 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} + * 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._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++) { + Edge.prototype._drawArrow = function(ctx) { + // set style + if (this.selected == true) {ctx.strokeStyle = this.color.highlight; ctx.fillStyle = this.color.highlight;} + else if (this.hover == true) {ctx.strokeStyle = this.color.hover; ctx.fillStyle = this.color.hover;} + else {ctx.strokeStyle = this.color.color; ctx.fillStyle = this.color.color;} - p0 = (i == 0) ? data[0] : data[i-1]; - p1 = data[i]; - p2 = data[i+1]; - p3 = (i + 2 < length) ? data[i+2] : p2; + ctx.lineWidth = this._getLineWidth(); + 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); - // 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 + 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; - // 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 }; + var via; + if (this.smoothCurves.dynamic == true && this.smoothCurves.enabled == true ) { + via = this.via; + } + else if (this.smoothCurves.enabled == true) { + via = this._getViaCoordinates(); + } - d += "C" + - bp1.x + "," + - bp1.y + " " + - bp2.x + "," + - bp2.y + " " + - p2.x + "," + - p2.y + " "; - } + if (this.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; - return d; - }; + var xTo,yTo; + if (this.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; + } - /** - * 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 - */ - LineGraph.prototype._catmullRom = function(data, group) { - var alpha = group.options.catmullRom.alpha; - if (alpha == 0 || alpha === undefined) { - return this._catmullRomUniform(data); - } - 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)); - - // 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 ] - - // [ 0 1 0 0 ] - // [ -d2pow2a/N A/N d1pow2a/N 0 ] - // [ 0 d3pow2a/M B/M -d2pow2a/M ] - // [ 0 0 1 0 ] - - 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); + ctx.beginPath(); + ctx.moveTo(xFrom,yFrom); + if (this.smoothCurves.enabled == true && via.x != null) { + ctx.quadraticCurveTo(via.x,via.y,xTo, yTo); + } + else { + ctx.lineTo(xTo, yTo); + } + ctx.stroke(); - 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;} + // draw arrow at the end of the line + length = (10 + 5 * this.width) * this.arrowScaleFactor; + ctx.arrow(xTo, yTo, angle, length); + ctx.fill(); + ctx.stroke(); - bp1 = { x: ((-d2pow2A * p0.x + A*p1.x + d1pow2A * p2.x) * N), - y: ((-d2pow2A * p0.y + A*p1.y + d1pow2A * p2.y) * N)}; + // draw label + if (this.label) { + var point; + if (this.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 { + // draw circle + var node = this.from; + var x, y, arrow; + var radius = 0.25 * Math.max(100,this.length); + 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(); - bp2 = { x: (( d3pow2A * p1.x + B*p2.x - d2pow2A * p3.x) * M), - y: (( d3pow2A * p1.y + B*p2.y - d2pow2A * p3.y) * M)}; + // draw all arrows + var length = (10 + 5 * this.width) * this.arrowScaleFactor; + ctx.arrow(arrow.x, arrow.y, arrow.angle, length); + ctx.fill(); + ctx.stroke(); - 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 + " "; + // draw label + if (this.label) { + point = this._pointOnCircle(x, y, radius, 0.5); + this._label(ctx, this.label, point.x, point.y); } - - return d; } }; + + /** - * this generates the SVG path for a linear drawing between datapoints. - * @param data - * @returns {string} + * 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._linear = function(data) { - // linear - var d = ""; - for (var i = 0; i < data.length; i++) { - if (i == 0) { - d += data[i].x + "," + data[i].y; + Edge.prototype._getDistanceToEdge = function (x1,y1, x2,y2, x3,y3) { // x3,y3 is the point + if (this.from != this.to) { + if (this.smoothCurves.enabled == true) { + var xVia, yVia; + if (this.smoothCurves.enabled == true && this.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 { - d += " " + data[i].x + "," + data[i].y; + return this._getDistanceToLine(x1,y1,x2,y2,x3,y3); } } - return d; + else { + var x, y, dx, dy; + var radius = this.length / 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); + } }; - module.exports = LineGraph; + 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; + } -/***/ }, -/* 37 */ -/***/ function(module, exports, __webpack_require__) { + var x = x1 + u * px, + y = y1 + u * py, + dx = x - x3, + dy = y - y3; - var util = __webpack_require__(1); - var DOMutil = __webpack_require__(6); - var Component = __webpack_require__(22); - var DataStep = __webpack_require__(38); + //# 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 +>>>>>>> b6ed63dda6f296069050476eabc9b3a9e165069f + + return Math.sqrt(dx*dx + dy*dy); + } /** - * A horizontal time axis - * @param {Object} [options] See DataAxis.setOptions for the available - * options. - * @constructor DataAxis - * @extends Component - * @param body +<<<<<<< HEAD + * draw a bar graph + * @param datapoints + * @param group */ - function DataAxis (body, options, svg) { - this.id = util.randomUUID(); - this.body = body; - - 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.linegraphSVG = svg; - this.props = {}; - this.DOMelements = { // dynamic elements - lines: {}, - labels: {} - }; - - this.dom = {}; - - this.range = {start:0, end:0}; - - this.options = util.extend({}, this.defaultOptions); - this.conversionFactor = 1; + 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; + var width = group.options.barChart.width; - this.setOptions(options); - this.width = Number(('' + this.options.width).replace("px","")); - this.minWidth = this.width; - this.height = this.linegraphSVG.offsetHeight; + if (group.options.barChart.align == 'left') {offset -= 0.5*width;} + else if (group.options.barChart.align == 'right') {offset += 0.5*width;} - this.stepPixels = 25; - this.stepPixelsForced = 25; - this.lineOffset = 0; - this.master = true; - this.svgElements = {}; + for (var i = 0; i < dataset.length; i++) { + // dynammically downscale the width so there is no overlap up to 1/10th the original width + 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 < width) {width = coreDistance < minWidth ? minWidth : coreDistance;} + DOMutil.drawBar(dataset[i].x + offset, dataset[i].y, width, group.zeroPosition - dataset[i].y, group.className + ' bar', this.svgElements, this.svg); + } - this.groups = {}; - this.amountOfGroups = 0; + // draw points + if (group.options.drawPoints.enabled == true) { + this._drawPoints(dataset, group, this.svgElements, this.svg, offset); + } + } + } + }; - // create the HTML DOM - this._create(); - } - DataAxis.prototype = new Component(); + /** + * draw a line graph + * + * @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); + } + // 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); - DataAxis.prototype.addGroup = function(label, graphOptions) { - if (!this.groups.hasOwnProperty(label)) { - this.groups[label] = graphOptions; - } - this.amountOfGroups += 1; + // draw points + if (group.options.drawPoints.enabled == true) { + this._drawPoints(dataset, group, this.svgElements, this.svg); + } + } +======= + * This allows the zoom level of the network to influence the rendering + * + * @param scale + */ + Edge.prototype.setScale = function(scale) { + this.networkScaleInv = 1.0/scale; }; - DataAxis.prototype.updateGroup = function(label, graphOptions) { - this.groups[label] = graphOptions; - }; - DataAxis.prototype.removeGroup = function(label) { - if (this.groups.hasOwnProperty(label)) { - delete this.groups[label]; - this.amountOfGroups -= 1; - } + Edge.prototype.select = function() { + this.selected = true; }; + Edge.prototype.unselect = function() { + this.selected = false; + }; - 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); - - this.minWidth = Number(('' + this.options.width).replace("px","")); - - if (redraw == true && this.dom.frame) { - this.hide(); - this.show(); - } + Edge.prototype.positionBezierNode = function() { + if (this.via !== null) { + this.via.x = 0.5 * (this.from.x + this.to.x); + this.via.y = 0.5 * (this.from.y + this.to.y); } }; - /** - * Create the HTML DOM for the DataAxis + * This function draws the control nodes for the manipulator. In order to enable this, only set the this.controlNodesEnabled to true. + * @param ctx */ - 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.dom.lineContainer = document.createElement('div'); - this.dom.lineContainer.style.width = '100%'; - this.dom.lineContainer.style.height = this.height; - - // 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); + 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); + } - var x; - var iconWidth = this.options.iconWidth; - var iconHeight = 15; - var iconOffset = 4; - var y = iconOffset + 0.5 * iconHeight; + 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 (this.options.orientation == 'left') { - x = iconOffset; + this.controlNodes.from.draw(ctx); + this.controlNodes.to.draw(ctx); } else { - x = this.width - iconWidth - iconOffset; - } - - 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; - } - } + this.controlNodes = {from:null, to:null, positions:{}}; +>>>>>>> b6ed63dda6f296069050476eabc9b3a9e165069f } - - DOMutil.cleanupElements(this.svgElements); }; /** - * Create the HTML DOM for the DataAxis +<<<<<<< HEAD + * draw the data points + * + * @param dataset + * @param JSONcontainer + * @param svg + * @param group */ - 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); - } - } - - if (!this.dom.lineContainer.parentNode) { - this.body.dom.backgroundHorizontal.appendChild(this.dom.lineContainer); + 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); } }; + + /** - * Create the HTML DOM for the DataAxis - */ - DataAxis.prototype.hide = function() { - if (this.dom.frame.parentNode) { - this.dom.frame.parentNode.removeChild(this.dom.frame); - } + * 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; - if (this.dom.lineContainer.parentNode) { - this.dom.lineContainer.parentNode.removeChild(this.dom.lineContainer); + var increment = 1; + var amountOfPoints = datapoints.length; + + 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))); } + + 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; +======= + * Enable control nodes. + * @private + */ + Edge.prototype._enableControlNodes = function() { + this.controlNodesEnabled = true; }; /** - * Set a range (start and end) - * @param end - * @param start - * @param end + * disable control nodes + * @private */ - DataAxis.prototype.setRange = function (start, end) { - this.range.start = start; - this.range.end = end; + Edge.prototype._disableControlNodes = function() { + this.controlNodesEnabled = false; }; /** - * Repaint the component - * @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 */ - 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++; - } - } + 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)); + + if (fromDistance < 15) { + this.connectedNode = this.from; + this.from = this.controlNodes.from; + return this.controlNodes.from; } - if (this.amountOfGroups == 0 || activeGroups == 0) { - this.hide(); + else if (toDistance < 15) { + this.connectedNode = this.to; + this.to = this.controlNodes.to; + return this.controlNodes.to; } else { - this.show(); - this.height = Number(this.linegraphSVG.style.height.replace("px","")); - // svg offsetheight did not work in firefox and explorer... - - this.dom.lineContainer.style.height = this.height + 'px'; - this.width = this.options.visible == true ? Number(('' + this.options.width).replace("px","")) : 0; + return null; +>>>>>>> b6ed63dda6f296069050476eabc9b3a9e165069f + } - var props = this.props; - var frame = this.dom.frame; +<<<<<<< HEAD + // extractedData.sort(function (a,b) {return a.x - b.x;}); + return {min: yMin, max: yMax, data: extractedData}; + }; - // update classname - frame.className = 'dataaxis'; + /** + * 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 + */ + LineGraph.prototype._convertYvalues = function (datapoints, group) { + var extractedData = []; + var xValue, yValue; + var axis = this.yAxisLeft; + var svgHeight = Number(this.svg.style.height.replace("px","")); - // calculate character width and height - this._calculateCharSize(); + if (group.options.yAxisOrientation == 'right') { + axis = this.yAxisRight; + } - var orientation = this.options.orientation; - var showMinorLabels = this.options.showMinorLabels; - var showMajorLabels = this.options.showMajorLabels; + 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}); +======= - // determine the width and height of the elemens for the axis - props.minorLabelHeight = showMinorLabels ? props.minorCharHeight : 0; - props.majorLabelHeight = showMajorLabels ? props.majorCharHeight : 0; + /** + * 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(); +>>>>>>> b6ed63dda6f296069050476eabc9b3a9e165069f + } - 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; +<<<<<<< HEAD + group.setZeroPosition(Math.min(svgHeight, axis.convertValue(0))); - // 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; + // extractedData.sort(function (a,b) {return a.x - b.x;}); + return extractedData; }; + /** - * Repaint major and minor text labels and vertical grid lines + * 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 */ - DataAxis.prototype._redrawLabels = function () { - DOMutil.prepareElements(this.DOMelements.lines); - DOMutil.prepareElements(this.DOMelements.labels); + 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++) { - var orientation = this.options['orientation']; + p0 = (i == 0) ? data[0] : data[i-1]; + p1 = data[i]; + p2 = data[i+1]; + p3 = (i + 2 < length) ? data[i+2] : p2; - // 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 amountOfSteps = this.height / stepPixels; - var stepDifference = 0; + // 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 - 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; - } + // 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 + " "; + } - this.valueAtZero = step.marginEnd; - var marginStartPos = 0; + return d; + }; - // do not draw the first label - var max = 1; - step.next(); + /** + * 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 + */ + LineGraph.prototype._catmullRom = function(data, group) { + var alpha = group.options.catmullRom.alpha; + if (alpha == 0 || alpha === undefined) { + return this._catmullRomUniform(data); + } + 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++) { - this.maxLabelSize = 0; - var y = 0; - while (max < Math.round(amountOfSteps)) { + p0 = (i == 0) ? data[0] : data[i-1]; + p1 = data[i]; + p2 = data[i+1]; + p3 = (i + 2 < length) ? data[i+2] : p2; - y = Math.round(max * stepPixels); - marginStartPos = max * stepPixels; - var isMajor = step.isMajor(); + 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)); - 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); - } + // 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 ] - 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); - } + // [ 0 1 0 0 ] + // [ -d2pow2a/N A/N d1pow2a/N 0 ] + // [ 0 d3pow2a/M B/M -d2pow2a/M ] + // [ 0 0 1 0 ] - step.next(); - max++; - } + 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.conversionFactor = marginStartPos/((amountOfSteps-1) * step.step); + 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;} - 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; - } - }; + 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)}; + + 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; +======= /** - * Create a label for the axis at position x - * @private - * @param y - * @param text - * @param orientation - * @param className - * @param characterHeight + * 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: *}}} */ - 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"; + 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; + + var via; + if (this.smoothCurves.dynamic == true && this.smoothCurves.enabled == true) { + via = this.via; } - else { - label.style.right = '-' + this.options.labelOffsetX + 'px'; - label.style.textAlign = "left"; + else if (this.smoothCurves.enabled == true) { + via = this._getViaCoordinates(); } - label.style.top = y - 0.5 * characterHeight + this.options.labelOffsetY + 'px'; - - text += ''; + if (this.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; - var largestWidth = Math.max(this.props.majorCharWidth,this.props.minorCharWidth); - if (this.maxLabelSize < text.length * largestWidth) { - this.maxLabelSize = text.length * largestWidth; + var xTo,yTo; + if (this.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; +>>>>>>> b6ed63dda6f296069050476eabc9b3a9e165069f } - }; +<<<<<<< HEAD /** - * Create a minor line for the axis at position y - * @param y - * @param orientation - * @param className - * @param offset - * @param width + * this generates the SVG path for a linear drawing between datapoints. + * @param data + * @returns {string} + * @private */ - 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'; + 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 { - line.style.right = (this.width - offset) + 'px'; + d += " " + data[i].x + "," + data[i].y; } - - line.style.width = width + 'px'; - line.style.top = y + 'px'; } + return d; }; - - 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 + module.exports = LineGraph; +======= + return {from:{x:xFrom,y:yFrom},to:{x:xTo,y:yTo}}; }; +>>>>>>> b6ed63dda6f296069050476eabc9b3a9e165069f + + module.exports = Edge; + +/***/ }, +<<<<<<< HEAD +/* 37 */ +/***/ function(module, exports, __webpack_require__) { + var util = __webpack_require__(1); + var DOMutil = __webpack_require__(6); + var Component = __webpack_require__(22); + var DataStep = __webpack_require__(38); /** - * 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 + * A horizontal time axis + * @param {Object} [options] See DataAxis.setOptions for the available + * options. + * @constructor DataAxis + * @extends Component + * @param body */ - 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); + function DataAxis (body, options, svg) { + this.id = util.randomUUID(); + this.body = body; - this.props.minorCharHeight = measureCharMinor.clientHeight; - this.props.minorCharWidth = measureCharMinor.clientWidth; + 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.dom.frame.removeChild(measureCharMinor); - } + this.linegraphSVG = svg; + this.props = {}; + this.DOMelements = { // dynamic elements + lines: {}, + labels: {} + }; - 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.dom = {}; - this.props.majorCharHeight = measureCharMajor.clientHeight; - this.props.majorCharWidth = measureCharMajor.clientWidth; + this.range = {start:0, end:0}; - this.dom.frame.removeChild(measureCharMajor); - } - }; - - /** - * 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); - }; - - module.exports = DataAxis; - - -/***/ }, -/* 38 */ -/***/ function(module, exports, __webpack_require__) { + this.options = util.extend({}, this.defaultOptions); + this.conversionFactor = 1; - /** - * @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; + this.setOptions(options); + this.width = Number(('' + this.options.width).replace("px","")); + this.minWidth = this.width; + this.height = this.linegraphSVG.offsetHeight; - this.autoScale = true; - this.stepIndex = 0; - this.step = 1; - this.scale = 1; + this.stepPixels = 25; + this.stepPixelsForced = 25; + this.lineOffset = 0; + this.master = true; + this.svgElements = {}; - this.marginStart; - this.marginEnd; - this.majorSteps = [1, 2, 5, 10]; - this.minorSteps = [0.25, 0.5, 1, 2]; + this.groups = {}; + this.amountOfGroups = 0; - this.setRange(start, end, minimumStep, containerHeight, forcedStepSize); + // create the HTML DOM + this._create(); } + DataAxis.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 {Number} [start] The start date and time. - * @param {Number} [end] The end date and time. - * @param {Number} [minimumStep] Optional. Minimum step size in milliseconds - */ - 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; + DataAxis.prototype.addGroup = function(label, graphOptions) { + if (!this.groups.hasOwnProperty(label)) { + this.groups[label] = graphOptions; } + this.amountOfGroups += 1; + }; - if (this.autoScale) { - this.setMinimumStep(minimumStep, containerHeight, forcedStepSize); + DataAxis.prototype.updateGroup = function(label, graphOptions) { + this.groups[label] = graphOptions; + }; + + DataAxis.prototype.removeGroup = function(label) { + if (this.groups.hasOwnProperty(label)) { + delete this.groups[label]; + this.amountOfGroups -= 1; } - this.setFirst(); }; - /** - * Automatically determine the scale that bests fits the provided minimum step - * @param {Number} [minimumStep] The minimum step size in milliseconds - */ - 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); - var minorStepIdx = -1; - var magnitudefactor = Math.pow(10,orderOfMagnitude); + 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 = 0; - if (orderOfMagnitude < 0) { - start = orderOfMagnitude; - } + this.minWidth = Number(('' + this.options.width).replace("px","")); - 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; + if (redraw == true && this.dom.frame) { + this.hide(); + this.show(); } } - this.stepIndex = minorStepIdx; - this.scale = magnitudefactor; - this.step = magnitudefactor * this.minorSteps[minorStepIdx]; }; +======= +/* 34 */ +/***/ function(module, exports, __webpack_require__) { + var util = __webpack_require__(1); /** - * Set the range iterator to the start date. + * @class Groups + * This class can store groups and properties specific for groups. */ - DataStep.prototype.first = function() { - this.setFirst(); - }; + function Groups() { + this.clear(); + this.defaultIndex = 0; + } + /** - * Round the current date to the first minor date value - * This must be executed once when the current date is set to start Date + * default constants for group colors */ - DataStep.prototype.setFirst = function() { - var niceStart = this._start - (this.scale * this.minorSteps[this.stepIndex]); - var niceEnd = this._end + (this.scale * this.minorSteps[this.stepIndex]); + 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 + ]; - this.marginEnd = this.roundToMinor(niceEnd); - this.marginStart = this.roundToMinor(niceStart); - this.marginRange = this.marginEnd - this.marginStart; +>>>>>>> b6ed63dda6f296069050476eabc9b3a9e165069f - this.current = this.marginEnd; + /** +<<<<<<< HEAD + * 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; + + this.dom.lineContainer = document.createElement('div'); + this.dom.lineContainer.style.width = '100%'; + this.dom.lineContainer.style.height = this.height; + + // 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); }; - 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]); + DataAxis.prototype._redrawGroupIcons = function () { + DOMutil.prepareElements(this.svgElements); + + var x; + var iconWidth = this.options.iconWidth; + var iconHeight = 15; + var iconOffset = 4; + var y = iconOffset + 0.5 * iconHeight; + + if (this.options.orientation == 'left') { + x = iconOffset; } else { - return rounded; + x = this.width - iconWidth - iconOffset; } - } + 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; + } + } + } - /** - * Check if the there is a next step - * @return {boolean} true if the current date has not passed the end date - */ - DataStep.prototype.hasNext = function () { - return (this.current >= this.marginStart); + DOMutil.cleanupElements(this.svgElements); }; /** - * Do the next step + * Create the HTML DOM for the DataAxis */ - 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; + 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); + } + } + + if (!this.dom.lineContainer.parentNode) { + this.body.dom.backgroundHorizontal.appendChild(this.dom.lineContainer); } }; /** - * Do the next step + * Create the HTML DOM for the DataAxis */ - DataStep.prototype.previous = function() { - this.current += this.step; - this.marginEnd += this.step; - this.marginRange = this.marginEnd - this.marginStart; - }; + DataAxis.prototype.hide = function() { + if (this.dom.frame.parentNode) { + this.dom.frame.parentNode.removeChild(this.dom.frame); + } + if (this.dom.lineContainer.parentNode) { + this.dom.lineContainer.parentNode.removeChild(this.dom.lineContainer); + } + }; + /** + * 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; + }; /** - * Get the current datetime - * @return {String} current The current date + * Repaint the component + * @return {boolean} Returns true if the component is resized */ - 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; + 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... - return toPrecision; + this.dom.lineContainer.style.height = this.height + 'px'; + this.width = this.options.visible == true ? Number(('' + this.options.width).replace("px","")) : 0; +======= + * 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++; + } + } + return i; + } }; - /** - * 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 + * 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 */ - DataStep.prototype.snap = function(date) { + 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; + } + return group; }; /** - * 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. + * Add a custom group style + * @param {String} groupname + * @param {Object} style An object containing borderColor, + * backgroundColor, etc. + * @return {Object} group The created group object */ - DataStep.prototype.isMajor = function() { - return (this.current % (this.scale * this.majorSteps[this.stepIndex]) == 0); + Groups.prototype.add = function (groupname, style) { + this.groups[groupname] = style; + if (style.color) { + style.color = util.parseColor(style.color); + } + return style; }; - module.exports = DataStep; + module.exports = Groups; +>>>>>>> b6ed63dda6f296069050476eabc9b3a9e165069f + + var props = this.props; + var frame = this.dom.frame; +<<<<<<< HEAD + // update classname + frame.className = 'dataaxis'; -/***/ }, -/* 39 */ -/***/ function(module, exports, __webpack_require__) { + // calculate character width and height + this._calculateCharSize(); - var util = __webpack_require__(1); - var DOMutil = __webpack_require__(6); + var orientation = this.options.orientation; + var showMinorLabels = this.options.showMinorLabels; + var showMajorLabels = this.options.showMajorLabels; - /** - * @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'] - 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; - } + // determine the width and height of the elemens for the axis + props.minorLabelHeight = showMinorLabels ? props.minorCharHeight : 0; + props.majorLabelHeight = showMajorLabels ? props.majorCharHeight : 0; - 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;}) + 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; + + // 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(); } } - else { - this.itemsData = []; - } + return changeCalled; }; - GraphGroup.prototype.setZeroPosition = function(pos) { - this.zeroPosition = pos; - }; + /** + * 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); - GraphGroup.prototype.setOptions = function(options) { - if (options !== undefined) { - var fields = ['sampling','style','sort','yAxisOrientation','barChart']; - util.selectiveDeepExtend(fields, this.options, options); + var orientation = this.options['orientation']; - util.mergeOptions(this.options, options,'catmullRom'); - util.mergeOptions(this.options, options,'drawPoints'); - util.mergeOptions(this.options, options,'shaded'); + // 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; - 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 amountOfSteps = this.height / stepPixels; + var stepDifference = 0; + + 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; } - }; - 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); - }; - GraphGroup.prototype.drawIcon = function(x, y, JSONcontainer, SVGcontainer, iconWidth, iconHeight) { - var fillHeight = iconHeight * 0.5; - var path, fillPath; + this.valueAtZero = step.marginEnd; + var marginStartPos = 0; - 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"); + // do not draw the first label + var max = 1; + step.next(); - 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"); + this.maxLabelSize = 0; + var y = 0; + while (max < Math.round(amountOfSteps)) { + + y = Math.round(max * stepPixels); + marginStartPos = max * stepPixels; + var isMajor = step.isMajor(); + + 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); } - if (this.options.drawPoints.enabled == true) { - DOMutil.drawPoint(x + 0.5 * iconWidth,y, this, JSONcontainer, SVGcontainer); + 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); + } + + step.next(); + max++; } - 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); + this.conversionFactor = marginStartPos/((amountOfSteps-1) * step.step); - 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); + 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; } }; /** - * - * @param iconWidth - * @param iconHeight - * @returns {{icon: HTMLElement, label: (group.content|*|string), orientation: (.options.yAxisOrientation|*)}} + * Create a label for the axis at position x + * @private + * @param y + * @param text + * @param orientation + * @param className + * @param characterHeight */ - 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; + 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"; + } + label.style.top = y - 0.5 * characterHeight + this.options.labelOffsetY + 'px'; -/***/ }, -/* 40 */ -/***/ function(module, exports, __webpack_require__) { + text += ''; - var util = __webpack_require__(1); - var DOMutil = __webpack_require__(6); - var Component = __webpack_require__(22); + var largestWidth = Math.max(this.props.majorCharWidth,this.props.minorCharWidth); + if (this.maxLabelSize < text.length * largestWidth) { + this.maxLabelSize = text.length * largestWidth; + } + }; /** - * Legend for Graph2d + * Create a minor line for the axis at position y + * @param y + * @param orientation + * @param className + * @param offset + * @param width */ - 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(); + 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 = ''; - this.setOptions(options); - } + if (orientation == 'left') { + line.style.left = (this.width - offset) + 'px'; + } + else { + line.style.right = (this.width - offset) + 'px'; + } - Legend.prototype = new Component(); + line.style.width = width + 'px'; + line.style.top = y + 'px'; +======= +/***/ }, +/* 35 */ +/***/ function(module, exports, __webpack_require__) { + /** + * @class Images + * This class loads images and keeps them stored. + */ + function Images() { + this.images = {}; - Legend.prototype.addGroup = function(label, graphOptions) { - if (!this.groups.hasOwnProperty(label)) { - this.groups[label] = graphOptions; - } - this.amountOfGroups += 1; - }; + this.callback = undefined; + } - Legend.prototype.updateGroup = function(label, graphOptions) { - this.groups[label] = graphOptions; + /** + * 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; }; - Legend.prototype.removeGroup = function(label) { - if (this.groups.hasOwnProperty(label)) { - delete this.groups[label]; - this.amountOfGroups -= 1; + /** + * + * @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; }; - 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"; + module.exports = Images; - 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'; +/***/ }, +/* 36 */ +/***/ function(module, exports, __webpack_require__) { - this.dom.frame.appendChild(this.svg); - this.dom.frame.appendChild(this.dom.textArea); - }; + var util = __webpack_require__(1); /** - * Hide the component from the DOM - */ - Legend.prototype.hide = function() { - // remove the frame containing the items - if (this.dom.frame.parentNode) { - this.dom.frame.parentNode.removeChild(this.dom.frame); - } - }; - - /** - * Show the component in the DOM (when not already visible). - * @return {Boolean} changed + * @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 + * */ - Legend.prototype.show = function() { - // show frame containing the items - if (!this.dom.frame.parentNode) { - this.body.dom.center.appendChild(this.dom.frame); - } - }; - - Legend.prototype.setOptions = function(options) { - var fields = ['enabled','orientation','icons','left','right']; - util.selectiveDeepExtend(fields, this.options, options); - }; + function Node(properties, imagelist, grouplist, constants) { + this.selected = false; + this.hover = false; - 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++; - } - } - } + this.edges = []; // all edges connected to this node + this.dynamicEdges = []; + this.reroutedEdges = {}; - 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 = ''; - } + this.group = constants.nodes.group; + this.fontSize = Number(constants.nodes.fontSize); + this.fontFace = constants.nodes.fontFace; + this.fontColor = constants.nodes.fontColor; + this.fontDrawThreshold = 3; - 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 = ''; - } + this.color = constants.nodes.color; - 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(); - } + // set defaults for the properties + this.id = undefined; + this.shape = constants.nodes.shape; + this.image = constants.nodes.image; + 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.radius = constants.nodes.radius; + this.baseRadiusValue = constants.nodes.radius; + this.radiusFixed = false; + this.radiusMin = constants.nodes.radiusMin; + this.radiusMax = constants.nodes.radiusMax; + this.level = -1; + this.preassignedLevel = false; + this.borderWidth = constants.nodes.borderWidth; + this.borderWidthSelected = constants.nodes.borderWidthSelected; - 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'; - } - }; - 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.imagelist = imagelist; + this.grouplist = grouplist; - this.svg.style.width = iconWidth + 5 + iconOffset + 'px'; + // 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.minForce = constants.minForce; + this.damping = constants.physics.damping; + this.mass = 1; // kg + this.fixedData = {x:null,y:null}; - 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); - } - }; + this.setProperties(properties, constants); - module.exports = Legend; + // creating the variables for clustering + this.resetCluster(); + this.dynamicEdgesLength = 0; + this.clusterSession = 0; + this.clusterSizeWidthFactor = constants.clustering.nodeScaling.width; + this.clusterSizeHeightFactor = constants.clustering.nodeScaling.height; + this.clusterSizeRadiusFactor = constants.clustering.nodeScaling.radius; + this.maxNodeSizeIncrements = constants.clustering.maxNodeSizeIncrements; + this.growthIndicator = 0; + // 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; + } -/***/ }, -/* 41 */ -/***/ function(module, exports, __webpack_require__) { + /** + * (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 = []; + }; - 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); + /** + * 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); +>>>>>>> b6ed63dda6f296069050476eabc9b3a9e165069f + } + this.dynamicEdgesLength = this.dynamicEdges.length; + }; - // Load custom shapes into CanvasRenderingContext2D - __webpack_require__(61); +<<<<<<< HEAD + 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 +======= /** - * @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 + * Detach a edge from the node + * @param {Edge} edge */ - function Network (container, data, options) { - if (!(this instanceof Network)) { - throw new SyntaxError('Constructor must be called with the new operator'); + 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; +>>>>>>> b6ed63dda6f296069050476eabc9b3a9e165069f + }; - this._initializeMixinLoaders(); - // create variables and set default values - this.containerElement = container; - this.width = '100%'; - this.height = '100%'; + /** +<<<<<<< HEAD + * 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); - // 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 - - this.stabilize = true; // stabilize before displaying the network - this.selectable = true; - this.initializing = true; - - // these functions are triggered when the dataset is edited - this.triggerFunctions = {add:null,edit:null,editEdge:null,connect:null,del:null}; + this.props.minorCharHeight = measureCharMinor.clientHeight; + this.props.minorCharWidth = measureCharMinor.clientWidth; + this.dom.frame.removeChild(measureCharMinor); + } - // set constant values - this.constants = { - nodes: { - 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 - 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 - }; - this.hoverObj = {nodes:{},edges:{}}; - this.controlNodesActive = false; + 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); - // 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(); - }); + this.props.majorCharHeight = measureCharMajor.clientHeight; + this.props.majorCharWidth = measureCharMajor.clientWidth; - // keyboard navigation variables - this.xIncrement = 0; - this.yIncrement = 0; - this.zoomIncrement = 0; + this.dom.frame.removeChild(measureCharMajor); + } + }; - // 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(); + /** + * 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); + }; - // apply options - this._setTranslation(this.frame.clientWidth / 2, this.frame.clientHeight / 2); - this._setScale(1); - this.setOptions(options); + module.exports = DataAxis; - // 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 +/***/ }, +/* 38 */ +/***/ function(module, exports, __webpack_require__) { - // 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 + /** + * @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; - // 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(); - } - }; + this.autoScale = true; + this.stepIndex = 0; + this.step = 1; + this.scale = 1; +======= + * 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; + } + 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.group !== undefined) {this.group = properties.group;} + 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;} + if (properties.borderWidth !== undefined) {this.borderWidth = properties.borderWidth;} + if (properties.borderWidthSelected !== undefined) {this.borderWidthSelected = properties.borderWidthSelected;} - // properties for the animation - this.moving = true; - this.timer = undefined; // Scheduling function. Is definded in this.start(); + // physics + if (properties.mass !== undefined) {this.mass = properties.mass;} - // 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); + // 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;} - // 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.stabilize == false) { - this.zoomExtent(true,this.constants.clustering.enabled); - } + if (this.id === undefined) { + throw "Node must have an id"; } - // if clustering is disabled, the simulation will have started in the setData function - if (this.constants.clustering.enabled) { - this.startWithClustering(); + // copy group properties + if (this.group !== undefined && this.group != "") { + var groupObj = this.grouplist.get(this.group); + for (var prop in groupObj) { + if (groupObj.hasOwnProperty(prop)) { + this[prop] = groupObj[prop]; + } + } } - } - // Extend Network with an Emitter mixin - Emitter(Network.prototype); + // individual shape properties + if (properties.shape !== undefined) {this.shape = properties.shape;} + if (properties.image !== undefined) {this.image = properties.image;} + if (properties.radius !== undefined) {this.radius = properties.radius; this.baseRadiusValue = this.radius;} + if (properties.color !== undefined) {this.color = util.parseColor(properties.color);} - /** - * 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 - */ - Network.prototype._getScriptPath = function() { - var scripts = document.getElementsByTagName( 'script' ); + if (properties.fontColor !== undefined) {this.fontColor = properties.fontColor;} + if (properties.fontSize !== undefined) {this.fontSize = properties.fontSize;} + if (properties.fontFace !== undefined) {this.fontFace = properties.fontFace;} - // 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); + if (this.image !== undefined && this.image != "") { + if (this.imagelist) { + this.imageObj = this.imagelist.load(this.image); + } + else { + throw "No imagelist provided"; } } - return null; - }; - + 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); - /** - * Find the center position of the network - * @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 (this.shape == 'image') { + this.radiusMin = constants.nodes.widthMin; + this.radiusMax = constants.nodes.widthMax; } - if (minX == 1e9 && maxX == -1e9 && minY == 1e9 && maxY == -1e9) { - minY = 0, maxY = 0, minX = 0, maxX = 0; + + // choose draw method depending on the shape + switch (this.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; } - return {minX: minX, maxX: maxX, minY: minY, maxY: maxY}; + // reset the size of the node, this can be changed + this._reset(); }; - /** - * @param {object} range = {minX: minX, maxX: maxX, minY: minY, maxY: maxY}; - * @returns {{x: number, y: number}} - * @private + * select this node */ - Network.prototype._findCenter = function(range) { - return {x: (0.5 * (range.maxX + range.minX)), - y: (0.5 * (range.maxY + range.minY))}; + Node.prototype.select = function() { + this.selected = true; + this._reset(); }; - /** - * center the network - * - * @param {object} range = {minX: minX, maxX: maxX, minY: minY, maxY: maxY}; + * unselect this node */ - Network.prototype._centerNetwork = function(range) { - var center = this._findCenter(range); + Node.prototype.unselect = function() { + this.selected = false; + this._reset(); + }; +>>>>>>> b6ed63dda6f296069050476eabc9b3a9e165069f - center.x *= this.scale; - center.y *= this.scale; - center.x -= 0.5 * this.frame.canvas.clientWidth; - center.y -= 0.5 * this.frame.canvas.clientHeight; + this.marginStart; + this.marginEnd; - this._setTranslation(-center.x,-center.y); // set at 0,0 - }; +<<<<<<< HEAD + this.majorSteps = [1, 2, 5, 10]; + this.minorSteps = [0.25, 0.5, 1, 2]; + this.setRange(start, end, minimumStep, containerHeight, forcedStepSize); + } - /** - * 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; - } - 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 { - 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. - } - } + /** + * 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 + */ + DataStep.prototype.setRange = function(start, end, minimumStep, containerHeight, forcedStepSize) { + this._start = start; + this._end = end; - // correct for larger canvasses. - var factor = Math.min(this.frame.canvas.clientWidth / 600, this.frame.canvas.clientHeight / 600); - zoomLevel *= factor; + if (start == end) { + this._start = start - 0.75; + this._end = end + 1; } - 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; - var xZoomLevel = this.frame.canvas.clientWidth / xDistance; - var yZoomLevel = this.frame.canvas.clientHeight / yDistance; + if (this.autoScale) { + this.setMinimumStep(minimumStep, containerHeight, forcedStepSize); +======= + /** + * Reset the calculated size of the node, forces it to recalculate its size + */ + Node.prototype.clearSizeCache = function() { + this._reset(); + }; - zoomLevel = (xZoomLevel <= yZoomLevel) ? xZoomLevel : yZoomLevel; - } + /** + * Reset the calculated size of the node, forces it to recalculate its size + * @private + */ + Node.prototype._reset = function() { + this.width = undefined; + this.height = undefined; + }; - if (zoomLevel > 1.0) { - zoomLevel = 1.0; + /** + * 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; + }; + + /** + * 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; + + if (!this.width) { + this.resize(ctx); } + switch (this.shape) { + case 'circle': + case 'dot': + return this.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 + } + else { + return 0; + } - this._setScale(zoomLevel); - this._centerNetwork(range); - if (disableStart == false) { - this.moving = true; - this.start(); } + // 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; + }; /** - * Update the this.nodeIndices with the most recent node index list + * Add forces acting on the node + * @param {number} fx Force in horizontal direction + * @param {number} fy Force in vertical direction * @private */ - Network.prototype._updateNodeIndexList = function() { - this._clearNodeIndexList(); - for (var idx in this.nodes) { - if (this.nodes.hasOwnProperty(idx)) { - this.nodeIndices.push(idx); - } - } + Node.prototype._addForce = function(fx, fy) { + this.fx += fx; + this.fy += fy; }; - /** - * 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. + * Perform one discrete step for the node + * @param {number} interval Time interval in seconds */ - Network.prototype.setData = function(data, disableStart) { - if (disableStart === undefined) { - disableStart = false; + Node.prototype.discreteStep = function(interval) { + if (!this.xFixed) { + var dx = this.damping * this.vx; // damping force + var ax = (this.fx - dx) / this.mass; // acceleration + this.vx += ax * interval; // velocity + this.x += this.vx * interval; // position } - 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.'); + if (!this.yFixed) { + var dy = this.damping * this.vy; // damping force + var ay = (this.fy - dy) / this.mass; // acceleration + this.vy += ay * interval; // velocity + this.y += this.vy * interval; // position +>>>>>>> b6ed63dda6f296069050476eabc9b3a9e165069f } + this.setFirst(); + }; - // set options - this.setOptions(data && data.options); - // set all data - if (data && data.dot) { - // parse DOT file - if(data && data.dot) { - var dotData = dotparser.DOTToGraph(data.dot); - this.setData(dotData); - return; - } + + /** +<<<<<<< HEAD + * Automatically determine the scale that bests fits the provided minimum step + * @param {Number} [minimumStep] The minimum step size in milliseconds + */ + 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); + + var minorStepIdx = -1; + var magnitudefactor = Math.pow(10,orderOfMagnitude); + + var start = 0; + if (orderOfMagnitude < 0) { + start = orderOfMagnitude; } - else if (data && data.gephi) { - // parse DOT file - if(data && data.gephi) { - var gephiData = gephiParser.parseGephi(data.gephi); - this.setData(gephiData); - return; + + 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; } } + this.stepIndex = minorStepIdx; + this.scale = magnitudefactor; + this.step = magnitudefactor * this.minorSteps[minorStepIdx]; +======= + * 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.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._setNodes(data && data.nodes); - this._setEdges(data && data.edges); + this.fx = 0; } - this._putDataInSector(); - if (!disableStart) { - // find a stable position or start animating to a stable position - if (this.stabilize) { - var me = this; - setTimeout(function() {me._stabilize(); me.start();},0) - } - else { - this.start(); - } + if (!this.yFixed) { + var dy = this.damping * this.vy; // damping force + var ay = (this.fy - dy) / this.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; } +>>>>>>> b6ed63dda6f296069050476eabc9b3a9e165069f }; /** - * Set options - * @param {Object} options - * @param {Boolean} [initializeView] | set zoom and translation to default. +<<<<<<< HEAD + * Set the range iterator to the start date. */ - Network.prototype.setOptions = function (options) { - if (options) { - var prop; - // retrieve parameter values - if (options.width !== undefined) {this.width = options.width;} - if (options.height !== undefined) {this.height = options.height;} - if (options.stabilize !== undefined) {this.stabilize = options.stabilize;} - if (options.selectable !== undefined) {this.selectable = options.selectable;} - if (options.freezeForStabilization !== undefined) {this.constants.freezeForStabilization = options.freezeForStabilization;} - if (options.configurePhysics !== undefined){this.constants.configurePhysics = options.configurePhysics;} - if (options.stabilizationIterations !== undefined) {this.constants.stabilizationIterations = options.stabilizationIterations;} - if (options.dragNetwork !== undefined) {this.constants.dragNetwork = options.dragNetwork;} - if (options.dragNodes !== undefined) {this.constants.dragNodes = options.dragNodes;} - if (options.zoomable !== undefined) {this.constants.zoomable = options.zoomable;} - if (options.hover !== undefined) {this.constants.hover = options.hover;} - if (options.hideEdgesOnDrag !== undefined) {this.constants.hideEdgesOnDrag = options.hideEdgesOnDrag;} - if (options.hideNodesOnDrag !== undefined) {this.constants.hideNodesOnDrag = options.hideNodesOnDrag;} + DataStep.prototype.first = function() { + this.setFirst(); + }; - // TODO: deprecated since version 3.0.0. Cleanup some day - if (options.dragGraph !== undefined) { - throw new Error('Option dragGraph is renamed to dragNetwork'); - } + /** + * 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]); - if (options.labels !== undefined) { - for (prop in options.labels) { - if (options.labels.hasOwnProperty(prop)) { - this.constants.labels[prop] = options.labels[prop]; - } - } - } + this.marginEnd = this.roundToMinor(niceEnd); + this.marginStart = this.roundToMinor(niceStart); + this.marginRange = this.marginEnd - this.marginStart; - if (options.onAdd) { - this.triggerFunctions.add = options.onAdd; - } + this.current = this.marginEnd; - if (options.onEdit) { - this.triggerFunctions.edit = options.onEdit; - } + }; - if (options.onEditEdge) { - this.triggerFunctions.editEdge = options.onEditEdge; - } + 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; + } + } - if (options.onConnect) { - this.triggerFunctions.connect = options.onConnect; - } - if (options.onDelete) { - this.triggerFunctions.del = options.onDelete; - } + /** + * Check if the there is a next step + * @return {boolean} true if the current date has not passed the end date + */ + DataStep.prototype.hasNext = function () { + return (this.current >= this.marginStart); + }; - if (options.physics) { - if (options.physics.barnesHut) { - this.constants.physics.barnesHut.enabled = true; - for (prop in options.physics.barnesHut) { - if (options.physics.barnesHut.hasOwnProperty(prop)) { - this.constants.physics.barnesHut[prop] = options.physics.barnesHut[prop]; - } - } - } + /** + * Do the next step + */ + DataStep.prototype.next = function() { + var prev = this.current; + this.current -= this.step; - if (options.physics.repulsion) { - this.constants.physics.barnesHut.enabled = false; - for (prop in options.physics.repulsion) { - if (options.physics.repulsion.hasOwnProperty(prop)) { - this.constants.physics.repulsion[prop] = options.physics.repulsion[prop]; - } - } - } + // safety mechanism: if current time is still unchanged, move to the end + if (this.current == prev) { + this.current = this._end; + } + }; - 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]; - } - } - } - } + /** + * Do the next step + */ + DataStep.prototype.previous = function() { + this.current += this.step; + this.marginEnd += this.step; + this.marginRange = this.marginEnd - this.marginStart; + }; - if (options.smoothCurves !== undefined) { - if (typeof options.smoothCurves == 'boolean') { - this.constants.smoothCurves.enabled = options.smoothCurves; - } - else { - this.constants.smoothCurves.enabled = true; - for (prop in options.smoothCurves) { - if (options.smoothCurves.hasOwnProperty(prop)) { - this.constants.smoothCurves[prop] = options.smoothCurves[prop]; - } - } - } - } - if (options.hierarchicalLayout) { - this.constants.hierarchicalLayout.enabled = true; - for (prop in options.hierarchicalLayout) { - if (options.hierarchicalLayout.hasOwnProperty(prop)) { - this.constants.hierarchicalLayout[prop] = options.hierarchicalLayout[prop]; - } - } - } - else if (options.hierarchicalLayout !== undefined) { - this.constants.hierarchicalLayout.enabled = false; - } - if (options.clustering) { - this.constants.clustering.enabled = true; - for (prop in options.clustering) { - if (options.clustering.hasOwnProperty(prop)) { - this.constants.clustering[prop] = options.clustering[prop]; - } - } + /** + * 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 (options.clustering !== undefined) { - this.constants.clustering.enabled = false; + else if (toPrecision[i] == "." || toPrecision[i] == ",") { + toPrecision = toPrecision.slice(0,i); + break; } + else{ + break; +======= + * 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); + }; - if (options.navigation) { - this.constants.navigation.enabled = true; - for (prop in options.navigation) { - if (options.navigation.hasOwnProperty(prop)) { - this.constants.navigation[prop] = options.navigation[prop]; - } - } - } - else if (options.navigation !== undefined) { - this.constants.navigation.enabled = false; - } + /** + * 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); + }; - if (options.keyboard) { - this.constants.keyboard.enabled = true; - for (prop in options.keyboard) { - if (options.keyboard.hasOwnProperty(prop)) { - this.constants.keyboard[prop] = options.keyboard[prop]; - } - } - } - else if (options.keyboard !== undefined) { - this.constants.keyboard.enabled = false; - } + /** + * check if this node is selecte + * @return {boolean} selected True if node is selected, else false + */ + Node.prototype.isSelected = function() { + return this.selected; + }; - if (options.dataManipulation) { - this.constants.dataManipulation.enabled = true; - for (prop in options.dataManipulation) { - if (options.dataManipulation.hasOwnProperty(prop)) { - this.constants.dataManipulation[prop] = options.dataManipulation[prop]; - } - } - this.editMode = this.constants.dataManipulation.initiallyVisible; - } - else if (options.dataManipulation !== undefined) { - this.constants.dataManipulation.enabled = false; - } + /** + * Retrieve the value of the node. Can be undefined + * @return {Number} value + */ + Node.prototype.getValue = function() { + return this.value; + }; - // TODO: work out these options and document them - if (options.edges) { - for (prop in options.edges) { - if (options.edges.hasOwnProperty(prop)) { - if (typeof options.edges[prop] != "object") { - this.constants.edges[prop] = options.edges[prop]; - } - } - } + /** + * 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); + }; - 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;} - } - } - - 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;} - } - } - - // Added to support dashed lines - // David Jordan - // 2012-08-08 - if (options.edges.dash) { - if (options.edges.dash.length !== undefined) { - this.constants.edges.dash.length = options.edges.dash.length; - } - if (options.edges.dash.gap !== undefined) { - this.constants.edges.dash.gap = options.edges.dash.gap; - } - if (options.edges.dash.altLength !== undefined) { - this.constants.edges.dash.altLength = options.edges.dash.altLength; - } - } - } - - if (options.nodes) { - for (prop in options.nodes) { - if (options.nodes.hasOwnProperty(prop)) { - this.constants.nodes[prop] = options.nodes[prop]; - } - } - - if (options.nodes.color) { - this.constants.nodes.color = util.parseColor(options.nodes.color); - } - /* - if (options.nodes.widthMin) this.constants.nodes.radiusMin = options.nodes.widthMin; - if (options.nodes.widthMax) this.constants.nodes.radiusMax = options.nodes.widthMax; - */ - } - if (options.groups) { - for (var groupname in options.groups) { - if (options.groups.hasOwnProperty(groupname)) { - var group = options.groups[groupname]; - this.groups.add(groupname, group); - } - } + /** + * 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.radius = (this.radiusMin + this.radiusMax) / 2; } - - 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); - } + else { + var scale = (this.radiusMax - this.radiusMin) / (max - min); + this.radius = (this.value - min) * scale + this.radiusMin; +>>>>>>> b6ed63dda6f296069050476eabc9b3a9e165069f } } - - - // (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.width, this.height); - this.moving = true; - this.start(); - + this.baseRadiusValue = this.radius; }; +<<<<<<< HEAD + return toPrecision; +======= /** - * 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 + * Draw this node in the given canvas + * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); + * @param {CanvasRenderingContext2D} ctx */ - Network.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.className = 'network-frame'; - this.frame.style.position = 'relative'; - this.frame.style.overflow = 'hidden'; + Node.prototype.draw = function(ctx) { + throw "Draw method not initialized for node"; +>>>>>>> b6ed63dda6f296069050476eabc9b3a9e165069f + }; - // 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) ); - // add the frame to the container element - this.containerElement.appendChild(this.frame); + /** +<<<<<<< HEAD + * 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) { }; - /** - * Binding the keys for keyboard navigation. These functions are defined in the NavigationMixin - * @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. */ - Network.prototype._createKeyBinds = function() { - var me = this; - this.mousetrap = mousetrap; + DataStep.prototype.isMajor = function() { + return (this.current % (this.scale * this.majorSteps[this.stepIndex]) == 0); + }; - this.mousetrap.reset(); + module.exports = DataStep; - 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)); - } - }; +/***/ }, +/* 39 */ +/***/ function(module, exports, __webpack_require__) { - /** - * Get the pointer location from a touch location - * @param {{pageX: Number, pageY: Number}} touch - * @return {{x: Number, y: Number}} pointer - * @private - */ - Network.prototype._getPointer = function (touch) { - return { - x: touch.pageX - util.getAbsoluteLeft(this.frame.canvas), - y: touch.pageY - util.getAbsoluteTop(this.frame.canvas) - }; - }; + var util = __webpack_require__(1); + var DOMutil = __webpack_require__(6); /** - * On start of a touch gesture, store the pointer - * @param event - * @private + * @constructor Group + * @param {Number | String} groupId + * @param {Object} data + * @param {ItemSet} itemSet */ - Network.prototype._onTouch = function (event) { - this.drag.pointer = this._getPointer(event.gesture.center); - this.drag.pinched = false; - this.pinch.scale = this._getScale(); + function GraphGroup (group, groupId, options, groupsUsingDefaultStyles) { + this.id = groupId; + var fields = ['sampling','style','sort','yAxisOrientation','barChart','drawPoints','shaded','catmullRom'] + 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; + } - this._handleTouch(this.drag.pointer); + 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;}) +======= + * 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"; }; /** - * handle drag start event - * @private + * 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 */ - Network.prototype._onDragStart = function () { - this._handleDragStart(); + 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); }; + Node.prototype._resizeImage = function (ctx) { + // TODO: pre calculate the image size - /** - * This function is called by _onDragStart. - * It is separated out because we can then overload it for the datamanipulation system. - * - * @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 - - drag.dragging = true; - drag.selection = []; - drag.translation = this._getTranslation(); - drag.nodeId = null; + if (!this.width || !this.height) { // undefined or 0 + var width, height; + if (this.value) { + this.radius = this.baseRadiusValue; + var scale = this.imageObj.height / this.imageObj.width; + if (scale !== undefined) { + width = this.radius || this.imageObj.width; + height = this.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; - if (node != null) { - drag.nodeId = node.id; - // select the clicked node if not yet selected - if (!node.isSelected()) { - this._selectObject(node,false); + 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.radius += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeRadiusFactor; + this.growthIndicator = this.width - width; } + } - // 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, + }; - // store original x, y, xFixed and yFixed, make the node temporarily Fixed - x: object.x, - y: object.y, - xFixed: object.xFixed, - yFixed: object.yFixed - }; + Node.prototype._drawImage = function (ctx) { + this._resizeImage(ctx); - object.xFixed = true; - object.yFixed = true; + this.left = this.x - this.width / 2; + this.top = this.y - this.height / 2; - drag.selection.push(s); - } + 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); + + ctx.globalAlpha = 0.5; + ctx.drawImage(this.imageObj, this.left - lineWidth, this.top - lineWidth, this.width + 2*lineWidth, this.height + 2*lineWidth); +>>>>>>> b6ed63dda6f296069050476eabc9b3a9e165069f } + + // 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 { +<<<<<<< HEAD + this.itemsData = []; } }; - - /** - * handle drag event - * @private - */ - Network.prototype._onDrag = function (event) { - this._handleOnDrag(event) + GraphGroup.prototype.setZeroPosition = function(pos) { + this.zeroPosition = pos; }; + GraphGroup.prototype.setOptions = function(options) { + if (options !== undefined) { + var fields = ['sampling','style','sort','yAxisOrientation','barChart']; + util.selectiveDeepExtend(fields, this.options, options); - /** - * This function is called by _onDrag. - * It is separated out because we can then overload it for the datamanipulation system. - * - * @private - */ - Network.prototype._handleOnDrag = function(event) { - if (this.drag.pinched) { - return; + util.mergeOptions(this.options, options,'catmullRom'); + util.mergeOptions(this.options, options,'drawPoints'); + util.mergeOptions(this.options, options,'shaded'); + + 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 pointer = this._getPointer(event.gesture.center); + 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 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; + GraphGroup.prototype.drawIcon = function(x, y, JSONcontainer, SVGcontainer, iconWidth, iconHeight) { + var fillHeight = iconHeight * 0.5; + var path, fillPath; - // update position of all selected nodes - selection.forEach(function (s) { - var node = s.node; + 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 (!s.xFixed) { - node.x = me._XconvertDOMtoCanvas(me._XconvertCanvasToDOM(s.x) + deltaX); + 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)); } - - if (!s.yFixed) { - node.y = me._YconvertDOMtoCanvas(me._YconvertCanvasToDOM(s.y) + deltaY); + 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"); + } - // start _animationStep if not yet running - if (!this.moving) { - this.moving = true; - this.start(); + if (this.options.drawPoints.enabled == true) { + DOMutil.drawPoint(x + 0.5 * iconWidth,y, this, JSONcontainer, SVGcontainer); } } 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; + var barWidth = Math.round(0.3 * iconWidth); + var bar1Height = Math.round(0.4 * iconHeight); + var bar2Height = Math.round(0.75 * iconHeight); - this._setTranslation( - this.drag.translation.x + diffX, - this.drag.translation.y + diffY - ); - this._redraw(); - // this.moving = true; - // this.start(); - } - } - }; + var offset = Math.round((iconWidth - (2 * barWidth))/3); - /** - * handle drag start event - * @private - */ - 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(); - } - else { - this._redraw(); + 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); +======= + // image still loading... just draw the label for now + yLabel = this.y; } + this._label(ctx, this.label, this.x, yLabel, undefined, "top"); }; - /** - * handle tap/click event: select/unselect a node - * @private - */ - Network.prototype._onTap = function (event) { - var pointer = this._getPointer(event.gesture.center); - this.pointerPosition = pointer; - this._handleTap(pointer); - }; + 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.radius += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeRadiusFactor; - /** - * handle doubletap event - * @private - */ - Network.prototype._onDoubleTap = function (event) { - var pointer = this._getPointer(event.gesture.center); - this._handleDoubleTap(pointer); + } }; + Node.prototype._drawBox = function (ctx) { + this._resizeBox(ctx); - /** - * handle long tap event: multi select nodes - * @private - */ - Network.prototype._onHold = function (event) { - var pointer = this._getPointer(event.gesture.center); - this.pointerPosition = pointer; - this._handleOnHold(pointer); - }; + this.left = this.x - this.width / 2; + this.top = this.y - this.height / 2; - /** - * handle the release of the screen - * - * @private - */ - Network.prototype._onRelease = function (event) { - var pointer = this._getPointer(event.gesture.center); - this._handleOnRelease(pointer); - }; + var clusterLineWidth = 2.5; + var borderWidth = this.borderWidth; + var selectionLineWidth = this.borderWidthSelected || 2 * this.borderWidth; - /** - * Handle pinch event - * @param event - * @private - */ - Network.prototype._onPinch = function (event) { - var pointer = this._getPointer(event.gesture.center); + ctx.strokeStyle = this.selected ? this.color.highlight.border : this.hover ? this.color.hover.border : this.color.border; - this.drag.pinched = true; - if (!('scale' in this.pinch)) { - this.pinch.scale = 1; - } + // 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); - // TODO: enabled moving while pinching? - var scale = this.pinch.scale * event.gesture.scale; - this._zoom(scale, pointer) - }; + ctx.roundRect(this.left-2*ctx.lineWidth, this.top-2*ctx.lineWidth, this.width+4*ctx.lineWidth, this.height+4*ctx.lineWidth, this.radius); + ctx.stroke(); +>>>>>>> b6ed63dda6f296069050476eabc9b3a9e165069f + } + ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); + ctx.lineWidth *= this.networkScaleInv; + ctx.lineWidth = Math.min(this.width,ctx.lineWidth); +<<<<<<< HEAD /** - * 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 + * + * @param iconWidth + * @param iconHeight + * @returns {{icon: HTMLElement, label: (group.content|*|string), orientation: (.options.yAxisOrientation|*)}} */ - 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; - } + 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}; + } - 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(); + module.exports = GraphGroup; - 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)}; +/***/ }, +/* 40 */ +/***/ function(module, exports, __webpack_require__) { - this._setScale(scale); - this._setTranslation(tx, ty); - this.updateClustersDefault(); + var util = __webpack_require__(1); + var DOMutil = __webpack_require__(6); + var Component = __webpack_require__(22); - if (preScaleDragPointer != null) { - var postScaleDragPointer = this.canvasToDOM(preScaleDragPointer); - this.drag.pointer.x = postScaleDragPointer.x; - this.drag.pointer.y = postScaleDragPointer.y; + /** + * Legend for Graph2d + */ + 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._redraw(); + this.svgElements = {}; + this.dom = {}; + this.groups = {}; + this.amountOfGroups = 0; + this._create(); - if (scaleOld < scale) { - this.emit("zoom", {direction:"+"}); - } - else { - this.emit("zoom", {direction:"-"}); - } + this.setOptions(options); + } - return scale; + Legend.prototype = new Component(); + + + Legend.prototype.addGroup = function(label, graphOptions) { + if (!this.groups.hasOwnProperty(label)) { + this.groups[label] = graphOptions; } + this.amountOfGroups += 1; }; + Legend.prototype.updateGroup = function(label, graphOptions) { + this.groups[label] = graphOptions; + }; - /** - * 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; + Legend.prototype.removeGroup = function(label) { + if (this.groups.hasOwnProperty(label)) { + delete this.groups[label]; + this.amountOfGroups -= 1; } + }; - // 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) { - - // calculate the new scale - var scale = this._getScale(); - var zoom = delta / 10; - if (delta < 0) { - zoom = zoom / (1 - zoom); - } - scale *= (1 + zoom); + 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"; - // calculate the pointer location - var gesture = hammerUtil.fakeGesture(this, event); - var pointer = this._getPointer(gesture.center); + this.dom.textArea = document.createElement('div'); + this.dom.textArea.className = 'legendText'; + this.dom.textArea.style.position = "relative"; + this.dom.textArea.style.top = "0px"; - // apply the new scale - this._zoom(scale, pointer); - } + 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'; - // Prevent default actions caused by mouse wheel. - event.preventDefault(); + this.dom.frame.appendChild(this.svg); + this.dom.frame.appendChild(this.dom.textArea); }; - /** - * Mouse move handler for checking whether the title moves over a node with a title. - * @param {Event} event - * @private + * Hide the component from the DOM */ - Network.prototype._onMouseMoveTitle = function (event) { - var gesture = hammerUtil.fakeGesture(this, event); - var pointer = this._getPointer(gesture.center); - - // check if the previously selected node is still selected - if (this.popupObj) { - this._checkHidePopup(pointer); + Legend.prototype.hide = function() { + // remove the frame containing the items + if (this.dom.frame.parentNode) { + this.dom.frame.parentNode.removeChild(this.dom.frame); } + }; - // 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); + /** + * Show the component in the DOM (when not already visible). + * @return {Boolean} changed + */ + Legend.prototype.show = function() { + // show frame containing the items + if (!this.dom.frame.parentNode) { + this.body.dom.center.appendChild(this.dom.frame); } + }; + Legend.prototype.setOptions = function(options) { + var fields = ['enabled','orientation','icons','left','right']; + util.selectiveDeepExtend(fields, this.options, options); + }; - /** - * 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]; + 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++; } } + } - // adding hover highlights - var obj = this._getNodeAt(pointer); - if (obj == null) { - obj = this._getEdgeAt(pointer); + 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 = ''; } - if (obj != null) { - this._hoverObject(obj); + 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 = ''; } - // 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]; + 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.redraw(); + this.dom.textArea.innerHTML = content; + this.dom.textArea.style.lineHeight = ((0.75 * this.options.iconSize) + this.options.iconSpacing) + 'px'; } }; - /** - * 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) - }; + 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; - var id; - var lastPopupNode = this.popupObj; + this.svg.style.width = iconWidth + 5 + iconOffset + 'px'; - 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; + 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 (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; - } - } - } + DOMutil.cleanupElements(this.svgElements); } + }; - 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); - } + module.exports = Legend; +======= + ctx.fillStyle = this.selected ? this.color.highlight.background : this.color.background; - // 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(); - } - } - else { - if (this.popup) { - this.popup.hide(); - } - } + ctx.roundRect(this.left, this.top, this.width, this.height, this.radius); + ctx.fill(); + ctx.stroke(); + + this._label(ctx, this.label, this.x, this.y); }; - /** - * 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(); - } + 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.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; - /** - * 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; + var clusterLineWidth = 2.5; + var borderWidth = this.borderWidth; + var selectionLineWidth = this.borderWidthSelected || 2 * this.borderWidth; - this.frame.canvas.style.width = '100%'; - this.frame.canvas.style.height = '100%'; + ctx.strokeStyle = this.selected ? this.color.highlight.border : this.hover ? this.color.hover.border : this.color.border; - this.frame.canvas.width = this.frame.canvas.clientWidth; - this.frame.canvas.height = this.frame.canvas.clientHeight; + // 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 (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"; - } + 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); - this.emit('resize', {width:this.frame.canvas.width,height:this.frame.canvas.height}); + ctx.fillStyle = this.selected ? this.color.highlight.background : this.hover ? this.color.hover.background : this.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); }; - /** - * 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; - 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'); - } + 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.radius = diameter / 2; - if (oldNodesData) { - // unsubscribe from old dataset - util.forEach(this.nodesListeners, function (callback, event) { - oldNodesData.off(event, callback); - }); + this.width = diameter; + this.height = diameter; + + // 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.radius += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeRadiusFactor; + this.growthIndicator = this.radius - 0.5*diameter; } + }; - // remove drawn nodes - this.nodes = {}; + Node.prototype._drawCircle = function (ctx) { + this._resizeCircle(ctx); + this.left = this.x - this.width / 2; + this.top = this.y - this.height / 2; - if (this.nodesData) { - // subscribe to new dataset - var me = this; - util.forEach(this.nodesListeners, function (callback, event) { - me.nodesData.on(event, callback); - }); + var clusterLineWidth = 2.5; + var borderWidth = this.borderWidth; + var selectionLineWidth = this.borderWidthSelected || 2 * this.borderWidth; - // draw all new nodes - var ids = this.nodesData.getIds(); - this._addNodes(ids); - } - this._updateSelection(); - }; + ctx.strokeStyle = this.selected ? this.color.highlight.border : this.hover ? this.color.hover.border : this.color.border; - /** - * 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 + // 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 ((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);} - } - this.moving = true; - } - this._updateNodeIndexList(); - if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { - this._resetLevels(); - this._setupHierarchicalLayout(); + ctx.circle(this.x, this.y, this.radius+2*ctx.lineWidth); + ctx.stroke(); } - this._updateCalculationNodes(); - this._reconnectEdges(); - this._updateValueRange(this.nodes); - this.updateLabels(); + 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.color.highlight.background : this.hover ? this.color.hover.background : this.color.background; + ctx.circle(this.x, this.y, this.radius); + ctx.fill(); + ctx.stroke(); + + this._label(ctx, this.label, this.x, this.y); }; - /** - * 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); - } - else { - // create node - node = new Node(properties, this.images, this.groups, this.constants); - nodes[id] = node; + 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; } - } - this.moving = true; - if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { - this._resetLevels(); - this._setupHierarchicalLayout(); - } - this._updateNodeIndexList(); - this._reconnectEdges(); - this._updateValueRange(nodes); - }; + var defaultSize = this.width; - /** - * 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(); + // 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.radius += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeRadiusFactor; + this.growthIndicator = this.width - defaultSize; } - this._updateCalculationNodes(); - this._reconnectEdges(); - this._updateSelection(); - this._updateValueRange(nodes); }; - /** - * 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; - - 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'); - } + Node.prototype._drawEllipse = function (ctx) { + this._resizeEllipse(ctx); + this.left = this.x - this.width / 2; + this.top = this.y - this.height / 2; - if (oldEdgesData) { - // unsubscribe from old dataset - util.forEach(this.edgesListeners, function (callback, event) { - oldEdgesData.off(event, callback); - }); - } + var clusterLineWidth = 2.5; + var borderWidth = this.borderWidth; + var selectionLineWidth = this.borderWidthSelected || 2 * this.borderWidth; - // remove drawn edges - this.edges = {}; + ctx.strokeStyle = this.selected ? this.color.highlight.border : this.hover ? this.color.hover.border : this.color.border; - if (this.edgesData) { - // subscribe to new dataset - var me = this; - util.forEach(this.edgesListeners, function (callback, event) { - me.edgesData.on(event, callback); - }); + // 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); - // draw all new nodes - var ids = this.edgesData.getIds(); - this._addEdges(ids); + 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); - this._reconnectEdges(); + ctx.fillStyle = this.selected ? this.color.highlight.background : this.hover ? this.color.hover.background : this.color.background; + + ctx.ellipse(this.left, this.top, this.width, this.height); + ctx.fill(); + ctx.stroke(); + this._label(ctx, this.label, this.x, this.y); }; - /** - * Add edges - * @param {Number[] | String[]} ids - * @private - */ - Network.prototype._addEdges = function (ids) { - var edges = this.edges, - edgesData = this.edgesData; + Node.prototype._drawDot = function (ctx) { + this._drawShape(ctx, 'circle'); + }; - for (var i = 0, len = ids.length; i < len; i++) { - var id = ids[i]; + Node.prototype._drawTriangle = function (ctx) { + this._drawShape(ctx, 'triangle'); + }; - var oldEdge = edges[id]; - if (oldEdge) { - oldEdge.disconnect(); - } + Node.prototype._drawTriangleDown = function (ctx) { + this._drawShape(ctx, 'triangleDown'); + }; - var data = edgesData.get(id, {"showInternalIds" : true}); - edges[id] = new Edge(data, this, this.constants); - } + Node.prototype._drawSquare = function (ctx) { + this._drawShape(ctx, 'square'); + }; - this.moving = true; - this._updateValueRange(edges); - this._createBezierNodes(); - if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { - this._resetLevels(); - this._setupHierarchicalLayout(); - } - this._updateCalculationNodes(); + Node.prototype._drawStar = function (ctx) { + this._drawShape(ctx, 'star'); }; - /** - * 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]; - - 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; - } - } + Node.prototype._resizeShape = function (ctx) { + if (!this.width) { + this.radius = this.baseRadiusValue; + var size = 2 * this.radius; + this.width = size; + this.height = size; +>>>>>>> b6ed63dda6f296069050476eabc9b3a9e165069f - this._createBezierNodes(); - if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { - this._resetLevels(); - this._setupHierarchicalLayout(); + // 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.radius += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeRadiusFactor; + this.growthIndicator = this.width - size; } - this.moving = true; - this._updateValueRange(edges); }; - /** - * 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]; - } - } + Node.prototype._drawShape = function (ctx, shape) { + this._resizeShape(ctx); - this.moving = true; - this._updateValueRange(edges); - if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { - this._resetLevels(); - this._setupHierarchicalLayout(); - } - this._updateCalculationNodes(); - }; + this.left = this.x - this.width / 2; + this.top = this.y - this.height / 2; - /** - * 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 = []; - } - } + var clusterLineWidth = 2.5; + var borderWidth = this.borderWidth; + var selectionLineWidth = this.borderWidthSelected || 2 * this.borderWidth; + var radiusMultiplier = 2; - for (id in edges) { - if (edges.hasOwnProperty(id)) { - var edge = edges[id]; - edge.from = null; - edge.to = null; - edge.connect(); - } + // 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; } - }; - /** - * 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; + ctx.strokeStyle = this.selected ? this.color.highlight.border : this.hover ? this.color.hover.border : this.color.border; - // 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); - } - } + // 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.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); - // adjust the range of all objects - if (valueMin !== undefined && valueMax !== undefined) { - for (id in obj) { - if (obj.hasOwnProperty(id)) { - obj[id].setValueRange(valueMin, valueMax); - } - } + ctx.fillStyle = this.selected ? this.color.highlight.background : this.hover ? this.color.hover.background : this.color.background; + ctx[shape](this.x, this.y, this.radius); + ctx.fill(); + ctx.stroke(); + + if (this.label) { + this._label(ctx, this.label, this.x, this.y + this.height / 2, undefined, 'top',true); } }; - /** - * Redraw the network with the current data - * chart will be resized too. - */ - Network.prototype.redraw = function() { - this.setSize(this.width, this.height); - this._redraw(); + 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; + + // 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.radius += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeRadiusFactor; + this.growthIndicator = this.width - (textSize.width + 2 * margin); + } }; - /** - * 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); + Node.prototype._drawText = function (ctx) { + this._resizeText(ctx); + this.left = this.x - this.width / 2; + this.top = this.y - this.height / 2; - // set scaling and translation - ctx.save(); - ctx.translate(this.translation.x, this.translation.y); - ctx.scale(this.scale, this.scale); + this._label(ctx, this.label, this.x, this.y); + }; - 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) - }; + Node.prototype._label = function (ctx, text, x, y, align, baseline, labelUnderNode) { + if (text && this.fontSize * this.networkScale > this.fontDrawThreshold) { + ctx.font = (this.selected ? "bold " : "") + this.fontSize + "px " + this.fontFace; + ctx.fillStyle = this.fontColor || "black"; + ctx.textAlign = align || "center"; + ctx.textBaseline = baseline || "middle"; - this._doInAllSectors("_drawAllSectorNodes",ctx); - if (this.drag.dragging == false || this.drag.dragging === undefined || this.constants.hideEdgesOnDrag == false) { - this._doInAllSectors("_drawEdges",ctx); - } + var lines = text.split('\n'); + var lineCount = lines.length; + var fontSize = (this.fontSize + 4); + var yLine = y + (1 - lineCount) / 2 * fontSize; + if (labelUnderNode == true) { + yLine = y + (1 - lineCount) / (2 * fontSize); + } - if (this.drag.dragging == false || this.drag.dragging === undefined || this.constants.hideNodesOnDrag == false) { - this._doInAllSectors("_drawNodes",ctx,false); + for (var i = 0; i < lineCount; i++) { + ctx.fillText(lines[i], x, yLine); + yLine += fontSize; + } } + }; - if (this.controlNodesActive == true) { - this._doInAllSectors("_drawControlNodes",ctx); - } - // this._doInSupportSector("_drawNodes",ctx,true); - // this._drawTree(ctx,"#F00F0F"); + Node.prototype.getTextSize = function(ctx) { + if (this.label !== undefined) { + ctx.font = (this.selected ? "bold " : "") + this.fontSize + "px " + this.fontFace; - // restore original scaling and translation - ctx.restore(); - }; + var lines = this.label.split('\n'), + height = (this.fontSize + 4) * lines.length, + width = 0; - /** - * 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 - }; - } + for (var i = 0, iMax = lines.length; i < iMax; i++) { + width = Math.max(width, ctx.measureText(lines[i]).width); + } - if (offsetX !== undefined) { - this.translation.x = offsetX; + return {"width": width, "height": height}; } - if (offsetY !== undefined) { - this.translation.y = offsetY; + else { + return {"width": 0, "height": 0}; } - - this.emit('viewChanged'); }; /** - * 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 - }; - }; - - /** - * Scale the network - * @param {Number} scale Scaling factor 1.0 is unscaled - * @private + * 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} */ - Network.prototype._setScale = function(scale) { - this.scale = scale; + 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; + } }; /** - * Get the current scale of the network - * @return {Number} scale Scaling factor 1.0 is unscaled - * @private + * checks if the core of the node is in the display area, this is used for opening clusters around zoom + * @returns {boolean} */ - Network.prototype._getScale = function() { - return this.scale; + 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); }; /** - * 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 + * 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 */ - Network.prototype._XconvertDOMtoCanvas = function(x) { - return (x - this.translation.x) / this.scale; + Node.prototype.setScaleAndPos = function(scale,canvasTopLeft,canvasBottomRight) { + this.networkScaleInv = 1.0/scale; + this.networkScale = scale; + this.canvasTopLeft = canvasTopLeft; + this.canvasBottomRight = canvasBottomRight; }; - /** - * 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; - }; /** - * 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 + * This allows the zoom level of the network to influence the rendering + * + * @param scale */ - Network.prototype._YconvertDOMtoCanvas = function(y) { - return (y - this.translation.y) / this.scale; + Node.prototype.setScale = function(scale) { + this.networkScaleInv = 1.0/scale; + this.networkScale = scale; }; + + /** - * 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 + * set the velocity at 0. Is called when this node is contained in another during clustering */ - Network.prototype._YconvertCanvasToDOM = function(y) { - return y * this.scale + this.translation.y ; + Node.prototype.clearVelocity = function() { + this.vx = 0; + this.vy = 0; }; /** + * Basic preservation of (kinectic) energy * - * @param {object} pos = {x: number, y: number} - * @returns {{x: number, y: number}} - * @constructor + * @param massBeforeClustering */ - Network.prototype.canvasToDOM = function(pos) { - return {x:this._XconvertCanvasToDOM(pos.x),y:this._YconvertCanvasToDOM(pos.y)}; - } + Node.prototype.updateVelocity = function(massBeforeClustering) { + var energyBefore = this.vx * this.vx * massBeforeClustering; + //this.vx = (this.vx < 0) ? -Math.sqrt(energyBefore/this.mass) : Math.sqrt(energyBefore/this.mass); + this.vx = Math.sqrt(energyBefore/this.mass); + energyBefore = this.vy * this.vy * massBeforeClustering; + //this.vy = (this.vy < 0) ? -Math.sqrt(energyBefore/this.mass) : Math.sqrt(energyBefore/this.mass); + this.vy = Math.sqrt(energyBefore/this.mass); + }; + + module.exports = Node; - /** - * - * @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)}; - } + +/***/ }, +/* 37 */ +/***/ function(module, exports, __webpack_require__) { /** - * Redraw all nodes - * The 2d context of a HTML canvas can be retrieved by canvas.getContext('2d'); - * @param {CanvasRenderingContext2D} ctx - * @param {Boolean} [alwaysShow] - * @private + * 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. */ - Network.prototype._drawNodes = function(ctx,alwaysShow) { - if (alwaysShow === undefined) { - alwaysShow = false; + function Popup(container, x, y, text, style) { + if (container) { + this.container = container; + } + else { + this.container = document.body; } - // 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); + // 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' } } } } - // 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); - } + 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); + } /** - * Redraw all edges - * The 2d context of a HTML canvas can be retrieved by canvas.getContext('2d'); - * @param {CanvasRenderingContext2D} ctx - * @private + * @param {number} x Horizontal position of the popup window + * @param {number} y Vertical position of the popup window */ - 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); - } - } - } + Popup.prototype.setPosition = function(x, y) { + this.x = parseInt(x); + this.y = parseInt(y); }; /** - * Redraw all edges - * The 2d context of a HTML canvas can be retrieved by canvas.getContext('2d'); - * @param {CanvasRenderingContext2D} ctx - * @private + * Set the text for the popup window. This can be HTML code + * @param {string} text */ - Network.prototype._drawControlNodes = function(ctx) { - var edges = this.edges; - for (var id in edges) { - if (edges.hasOwnProperty(id)) { - edges[id]._drawControlNodes(ctx); - } - } + Popup.prototype.setText = function(text) { + this.frame.innerHTML = text; }; /** - * Find a stable position for all nodes - * @private + * Show the popup window + * @param {boolean} show Optional. Show or hide the window */ - Network.prototype._stabilize = function() { - if (this.constants.freezeForStabilization == true) { - this._freezeDefinedNodes(); + Popup.prototype.show = function (show) { + if (show === undefined) { + show = true; } - // find stable position - var count = 0; - while (this.moving && count < this.constants.stabilizationIterations) { - this._physicsTick(); - count++; + if (show) { + var height = this.frame.clientHeight; + var width = this.frame.clientWidth; + var maxHeight = this.frame.parentNode.clientHeight; + var maxWidth = this.frame.parentNode.clientWidth; + + 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"; } - this.zoomExtent(false,true); - if (this.constants.freezeForStabilization == true) { - this._restoreFrozenNodes(); + else { + this.hide(); } - this.emit("stabilized",{iterations:count}); }; /** - * 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 + * Hide the popup window */ - 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; - } - } - } + Popup.prototype.hide = function () { + this.frame.style.visibility = "hidden"; }; + module.exports = Popup; + + +/***/ }, +/* 38 */ +/***/ function(module, exports, __webpack_require__) { + /** - * Unfreezes the nodes that have been frozen by _freezeDefinedNodes. + * 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. * - * @private + * 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 */ - 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; - } - } - } + function parseDOT (data) { + dot = data; + return parseGraph(); + } + + // token types enumeration + var TOKENTYPE = { + NULL : 0, + DELIMITER : 1, + IDENTIFIER: 2, + UNKNOWN : 3 + }; + + // map with all delimiters + var DELIMITERS = { + '{': true, + '}': true, + '[': true, + ']': true, + ';': true, + '=': true, + ',': true, + + '->': true, + '--': true }; + 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 /** - * 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 + * 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. */ - Network.prototype._isMoving = function(vmin) { - var nodes = this.nodes; - for (var id in nodes) { - if (nodes.hasOwnProperty(id) && nodes[id].isMoving(vmin)) { - return true; - } - } - return false; - }; + function first() { + index = 0; + c = dot.charAt(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); + } /** - * /** - * Perform one discrete step for all nodes - * - * @private + * Preview the next character from the dot file. + * @return {String} cNext */ - Network.prototype._discreteStepNodes = function() { - var interval = this.physicsDiscreteStepsize; - var nodes = this.nodes; - var nodeId; - var nodesPresent = false; + function nextPreview() { + return dot.charAt(index + 1); + } - 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; - } - } + /** + * 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); + } + + /** + * 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 = {}; } - 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}); + if (b) { + for (var name in b) { + if (b.hasOwnProperty(name)) { + a[name] = b[name]; } - this.moving = this.moving || this.configurePhysics; - } } - }; + return a; + } /** - * A single simulation step (or "tick") in the physics simulation + * Set a value in an object, where the provided parameter name can be a + * path with nested parameters. For example: * - * @private + * 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 */ - 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"); + 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] = {}; } - this._findCenter(this._getRange()) + o = o[key]; + } + else { + // this is the end point + o[key] = value; } } - }; - + } /** - * 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 + * 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 */ - 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(); - - // this schedules a new animation step - this.start(); + function addNode(graph, node) { + var i, len; + var current = null; - // 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++; + // 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; } - // start the rendering process - var renderTime = Date.now(); - this._redraw(); - this.renderTime = Date.now() - renderTime; - - }; - - if (typeof window !== 'undefined') { - window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || - window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; - } - - /** - * 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; - } + // 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; } + } + } - 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 - } + if (!current) { + // this is a new node + current = { + id: node.id + }; + if (graph.node) { + // clone default attributes + current.attr = merge(current.attr, graph.node); } } - else { - this._redraw(); + + // add node to this (sub)graph and all its parent graphs + for (i = graphs.length - 1; i >= 0; i--) { + var g = graphs[i]; + + if (!g.nodes) { + g.nodes = []; + } + if (g.nodes.indexOf(current) == -1) { + g.nodes.push(current); + } } - }; + // merge attributes + if (node.attr) { + current.attr = merge(current.attr, node.attr); + } + } /** - * Move the network according to the keyboard presses. - * - * @private + * Add an edge to a graph object + * @param {Object} graph + * @param {Object} edge */ - 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); + function addEdge(graph, edge) { + if (!graph.edges) { + graph.edges = []; } - 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); + graph.edges.push(edge); + if (graph.edge) { + var attr = merge({}, graph.edge); // clone default attributes + edge.attr = merge(attr, edge.attr); // merge attributes } - }; - + } /** - * Freeze the _animationStep + * 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 */ - Network.prototype.toggleFreeze = function() { - if (this.freezeSimulation == false) { - this.freezeSimulation = true; - } - else { - this.freezeSimulation = false; - this.start(); + function createEdge(graph, from, to, type, attr) { + var edge = { + from: from, + to: to, + type: type + }; + + if (graph.edge) { + edge.attr = merge({}, graph.edge); // clone default attributes } - }; + edge.attr = merge(edge.attr || {}, attr); // merge attributes + return edge; + } /** - * This function cleans the support nodes if they are not needed and adds them when they are. - * - * @param {boolean} [disableStart] - * @private + * Get next token in the current dot file. + * The token and token type are available as token and tokenType */ - Network.prototype._configureSmoothCurves = function(disableStart) { - if (disableStart === undefined) { - disableStart = true; + function getToken() { + tokenType = TOKENTYPE.NULL; + token = ''; + + // skip over whitespaces + while (c == ' ' || c == '\t' || c == '\n' || c == '\r') { // space, tab, enter + next(); } - 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]] === undefined) { - delete this.sectors['support']['nodes'][nodeId]; + + do { + var isComment = false; + + // 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; } } - } - else { - // delete the support nodes - this.sectors['support']['nodes'] = {}; - for (var edgeId in this.edges) { - if (this.edges.hasOwnProperty(edgeId)) { - this.edges[edgeId].smooth = false; - this.edges[edgeId].via = null; + if (c == '/' && nextPreview() == '/') { + // skip line comment + while (c != '' && c != '\n') { + next(); } + isComment = true; } - } - - - this._updateCalculationNodes(); - if (!disableStart) { - this.moving = true; - this.start(); - } - }; - - - /** - * 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) { - edge.smooth = true; - 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(); + 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; } - } - }; - /** - * 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]; + // skip over whitespaces + while (c == ' ' || c == '\t' || c == '\n' || c == '\r') { // space, tab, enter + next(); } } - }; + while (isComment); - /** - * 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}); + // check for end of dot file + if (c == '') { + // token is still empty + tokenType = TOKENTYPE.DELIMITER; + return; + } + + // check for delimiters consisting of 2 characters + var c2 = c + nextPreview(); + if (DELIMITERS[c2]) { + tokenType = TOKENTYPE.DELIMITER; + token = c2; + next(); + next(); + return; + } + + // 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(); } + next(); } + if (c != '"') { + throw newSyntaxError('End of string " expected'); + } + next(); + tokenType = TOKENTYPE.IDENTIFIER; + return; } - this.nodesData.update(dataArray); - }; + // 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) + '"'); + } /** - * Center a node in view. - * - * @param {Number} nodeId - * @param {Number} [zoomLevel] + * Parse a graph. + * @returns {Object} graph */ - 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}; + function parseGraph() { + var graph = {}; - var requiredScale = zoomLevel; - this._setScale(requiredScale); + first(); + getToken(); - var canvasCenter = this.DOMtoCanvas({x:0.5 * this.frame.canvas.width,y:0.5 * this.frame.canvas.height}); - var translation = this._getTranslation(); + // optional strict keyword + if (token == 'strict') { + graph.strict = true; + getToken(); + } - var distanceFromCenter = {x:canvasCenter.x - nodePosition.x, - y:canvasCenter.y - nodePosition.y}; + // graph or digraph keyword + if (token == 'graph' || token == 'digraph') { + graph.type = token; + getToken(); + } - this._setTranslation(translation.x + requiredScale * distanceFromCenter.x, - translation.y + requiredScale * distanceFromCenter.y); - this.redraw(); + // optional graph id + if (tokenType == TOKENTYPE.IDENTIFIER) { + graph.id = token; + getToken(); } - else { - console.log("This nodeId cannot be found.") + + // open angle bracket + if (token != '{') { + throw newSyntaxError('Angle bracket { expected'); } - }; + getToken(); - module.exports = Network; + // statements + parseStatements(graph); + // close angle bracket + if (token != '}') { + throw newSyntaxError('Angle bracket } expected'); + } + getToken(); -/***/ }, -/* 42 */ -/***/ function(module, exports, __webpack_require__) { + // 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; + } /** - * 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 + * Parse a list with statements. + * @param {Object} graph */ + function parseStatements (graph) { + while (token !== '' && token != '}') { + parseStatement(graph); + if (token == ';') { + getToken(); + } + } + } - /** - * 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' - }, - - /** - * 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: '\'' - }, + /** + * 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); - /** - * 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', - '_': '-', - '+': '=', - ':': ';', - '\"': '\'', - '<': ',', - '>': '.', - '?': '/', - '|': '\\' - }, + return; + } - /** - * 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' - }, + // parse an attribute statement + var attr = parseAttributeStatement(graph); + if (attr) { + return; + } - /** - * 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, + // parse node + if (tokenType != TOKENTYPE.IDENTIFIER) { + throw newSyntaxError('Identifier expected'); + } + var id = token; // id can be a string or a number + getToken(); - /** - * a list of all the callbacks setup via Mousetrap.bind() - * - * @type {Object} - */ - _callbacks = {}, + 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); + } + } - /** - * direct map of string combinations to callbacks used for trigger() - * - * @type {Object} - */ - _direct_map = {}, + /** + * Parse a subgraph + * @param {Object} graph parent graph object + * @return {Object | null} subgraph + */ + function parseSubgraph (graph) { + var subgraph = null; - /** - * keeps track of what level each sequence is at since multiple - * sequences can start out with the same sequence - * - * @type {Object} - */ - _sequence_levels = {}, + // optional subgraph keyword + if (token == 'subgraph') { + subgraph = {}; + subgraph.type = 'subgraph'; + getToken(); - /** - * variable to store the setTimeout call - * - * @type {null|number} - */ - _reset_timer, + // optional graph id + if (tokenType == TOKENTYPE.IDENTIFIER) { + subgraph.id = token; + getToken(); + } + } - /** - * temporary state where we will ignore the next keyup - * - * @type {boolean|string} - */ - _ignore_next_keyup = false, + // open angle bracket + if (token == '{') { + getToken(); - /** - * are we currently inside of a sequence? - * type of action ("keyup" or "keydown" or "keypress") or false - * - * @type {boolean|string} - */ - _inside_sequence = false; + if (!subgraph) { + subgraph = {}; + } + subgraph.parent = graph; + subgraph.node = graph.node; + subgraph.edge = graph.edge; + subgraph.graph = graph.graph; - /** - * 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; - } + // statements + parseStatements(subgraph); - /** - * loop through to map numbers on the numeric keypad - */ - for (i = 0; i <= 9; ++i) { - _MAP[i + 96] = i; - } + // close angle bracket + if (token != '}') { + throw newSyntaxError('Angle bracket } expected'); + } + getToken(); - /** - * 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); - } + // remove temporary default properties + delete subgraph.node; + delete subgraph.edge; + delete subgraph.graph; + delete subgraph.parent; - object.attachEvent('on' + type, callback); + // register at the parent graph + if (!graph.subgraphs) { + graph.subgraphs = []; + } + graph.subgraphs.push(subgraph); } - /** - * takes the event and returns the key character - * - * @param {Event} e - * @return {string} - */ - function _characterFromEvent(e) { - - // for keypress events we should return the character as is - if (e.type == 'keypress') { - return String.fromCharCode(e.which); - } - - // for non keypress events the special maps are needed - if (_MAP[e.which]) { - return _MAP[e.which]; - } + return subgraph; + } - if (_KEYCODE_MAP[e.which]) { - return _KEYCODE_MAP[e.which]; - } + /** + * 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(); - // if it is not in the special map - return String.fromCharCode(e.which).toLowerCase(); + // node attributes + graph.node = parseAttributeList(); + return 'node'; } + else if (token == 'edge') { + getToken(); - /** - * 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; - - // if the element has the class "mousetrap" then no need to stop - if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) { - return false; - } + // edge attributes + graph.edge = parseAttributeList(); + return 'edge'; + } + else if (token == 'graph') { + getToken(); - // stop for input, select, and textarea - return tag_name == 'INPUT' || tag_name == 'SELECT' || tag_name == 'TEXTAREA' || (element.contentEditable && element.contentEditable == 'true'); + // graph attributes + graph.graph = parseAttributeList(); + return 'graph'; } - /** - * 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; - - for (key in _sequence_levels) { - if (do_not_reset[key]) { - active_sequences = true; - continue; - } - _sequence_levels[key] = 0; - } + return null; + } - if (!active_sequences) { - _inside_sequence = false; - } + /** + * 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); - /** - * 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 = []; + // edge statements + parseEdge(graph, id); + } - // if there are no events related to this keycode - if (!_callbacks[character]) { - return []; - } + /** + * 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(); - // if a modifier key is coming up on its own we should allow it - if (action == 'keyup' && _isModifier(character)) { - modifiers = [character]; + 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(); + } - // 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]; - - // 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 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)) { - - // 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); - } + // parse edge attributes + var attr = parseAttributeList(); - matches.push(callback); - } - } + // create edge + var edge = createEdge(graph, from, to, type, attr); + addEdge(graph, edge); - return matches; + from = to; } + } - /** - * takes a key event and figures out what the modifiers are - * - * @param {Event} e - * @returns {Array} - */ - function _eventModifiers(e) { - var modifiers = []; + /** + * Parse a set with attributes, + * for example [label="1.000", shape=solid] + * @return {Object | null} attr + */ + function parseAttributeList() { + var attr = null; - if (e.shiftKey) { - modifiers.push('shift'); + while (token == '[') { + getToken(); + attr = {}; + while (token !== '' && token != ']') { + if (tokenType != TOKENTYPE.IDENTIFIER) { + throw newSyntaxError('Attribute name expected'); } + var name = token; - if (e.altKey) { - modifiers.push('alt'); + getToken(); + if (token != '=') { + throw newSyntaxError('Equal sign = expected'); } + getToken(); - if (e.ctrlKey) { - modifiers.push('ctrl'); + if (tokenType != TOKENTYPE.IDENTIFIER) { + throw newSyntaxError('Attribute value expected'); } + var value = token; + setValue(attr, name, value); // name can be a path - if (e.metaKey) { - modifiers.push('meta'); + getToken(); + if (token ==',') { + getToken(); } + } - return modifiers; + if (token != ']') { + throw newSyntaxError('Bracket ] expected'); + } + getToken(); } - /** - * 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(); - } + return attr; + } - if (e.stopPropagation) { - e.stopPropagation(); - } + /** + * 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 + ')'); + } - e.returnValue = false; - e.cancelBubble = true; + /** + * 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); + } } + } - /** - * handles a character key event - * - * @param {string} character - * @param {Event} e - * @returns void - */ - function _handleCharacter(character, e) { + /** + * 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: {} + }; - // if this event should not happen stop here - if (_stop(e)) { - return; + // 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); + }); + } - var callbacks = _getMatches(character, _eventModifiers(e), e.type), - i, - do_not_reset = {}, - processed_sequence_callback = false; - - // loop through matching callbacks for this key event - for (i = 0; i < callbacks.length; ++i) { + // 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; + } - // 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; + dotData.edges.forEach(function (dotEdge) { + var from, to; + if (dotEdge.from instanceof Object) { + from = dotEdge.from.nodes; + } + else { + from = { + id: dotEdge.from + } + } - // keep a list of which sequences were matches for later - do_not_reset[callbacks[i].seq] = 1; - _fireCallback(callbacks[i].callback, e); - continue; - } + if (dotEdge.to instanceof Object) { + to = dotEdge.to.nodes; + } + else { + to = { + id: dotEdge.to + } + } - // 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 (dotEdge.from instanceof Object && dotEdge.from.edges) { + dotEdge.from.edges.forEach(function (subEdge) { + var graphEdge = convertEdge(subEdge); + graphData.edges.push(graphEdge); + }); } - // 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); + 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); + }); } + }); } - /** - * handles a keydown event - * - * @param {Event} e - * @returns void - */ - function _handleKey(e) { + // copy the options + if (dotData.attr) { + graphData.options = dotData.attr; + } - // 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; + return graphData; + } - var character = _characterFromEvent(e); + // exports + exports.parseDOT = parseDOT; + exports.DOTToGraph = DOTToGraph; - // no character found then stop - if (!character) { - return; - } - if (e.type == 'keyup' && _ignore_next_keyup == character) { - _ignore_next_keyup = false; - return; - } +/***/ }, +/* 39 */ +/***/ function(module, exports, __webpack_require__) { - _handleCharacter(character, e); + + 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; } - /** - * 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 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); } - /** - * 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); + 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); } - /** - * 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) { + return {nodes:nodes, edges:edges}; + } - // 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; - } + exports.parseGephi = parseGephi; - if (_MAP.hasOwnProperty(key)) { - _REVERSE_MAP[_MAP[key]] = key; - } - } - } - return _REVERSE_MAP; - } +/***/ }, +/* 40 */ +/***/ function(module, exports, __webpack_require__) { - /** - * 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) { + // 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); - // 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'; - } - // modifier keys don't work as expected with keypress, - // switch to keydown - if (action == 'keypress' && modifiers.length) { - action = 'keydown'; - } +/***/ }, +/* 41 */ +/***/ function(module, exports, __webpack_require__) { - return action; + // 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.'); } + } - /** - * 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], []); - } +/***/ }, +/* 42 */ +/***/ function(module, exports, __webpack_require__) { - /** - * 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(); - }, + var Hammer = __webpack_require__(41); - /** - * 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); + /** + * 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; - // 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); - } + // for hammer.js 1.0.5 + // var gesture = Hammer.event.collectEventData(this, eventType, event); - // weird race condition if a sequence ends with the key - // another sequence begins with - setTimeout(_resetSequences, 10); - }, - i; + // for hammer.js 1.0.6+ + var touches = Hammer.event.getTouchList(event, eventType); + var gesture = Hammer.event.collectEventData(this, eventType, touches, event); - // 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); - } + // 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; } - /** - * 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) { - - // make sure multiple spaces in a row become a single space - combination = combination.replace(/\s+/g, ' '); + return gesture; + }; - var sequence = combination.split(' '), - i, - key, - keys, - modifiers = []; - // 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); - } +/***/ }, +/* 43 */ +/***/ function(module, exports, __webpack_require__) { - // take the keys from this pattern and figure out what the actual - // pattern is all about - keys = combination === '+' ? ['+'] : combination.split('+'); + /** + * Canvas shapes used by Network + */ + if (typeof CanvasRenderingContext2D !== 'undefined') { - for (i = 0; i < keys.length; ++i) { - key = keys[i]; + /** + * Draw a circle shape + */ + CanvasRenderingContext2D.prototype.circle = function(x, y, r) { + this.beginPath(); + this.arc(x, y, r, 0, 2*Math.PI, false); + }; - // normalize key names - if (_SPECIAL_ALIASES[key]) { - key = _SPECIAL_ALIASES[key]; - } + /** + * 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 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'); - } + /** + * 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(); - // if this key is a modifier then add it to the list of modifiers - if (_isModifier(key)) { - modifiers.push(key); - } - } + 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 - // depending on what the key combination is - // we will try to pick the best event for it - action = _pickBestAction(key, modifiers, action); + 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(); + }; - // make sure to initialize array if this is the first time - // a callback is added for this key - if (!_callbacks[key]) { - _callbacks[key] = []; - } + /** + * 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(); - // remove an existing match if there is one - _getMatches(key, modifiers, action, !sequence_name, combination); + 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 - // 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 - }); - } + 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(); + }; /** - * binds multiple combinations to the same callback - * - * @param {Array} combinations - * @param {Function} callback - * @param {string|undefined} action - * @returns void + * 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 */ - 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); - - var mousetrap = { + CanvasRenderingContext2D.prototype.star = function(x, y, r) { + // http://www.html5canvastutorials.com/labs/html5-canvas-star-spinner/ + this.beginPath(); - /** - * 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; - }, + 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) + ); + } - /** - * 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; - }, + this.closePath(); + }; - /** - * 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; - }, + /** + * 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); + }; - /** - * 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; - } + /** + * 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); }; - module.exports = mousetrap; + /** + * 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; -/***/ }, -/* 43 */ -/***/ function(module, exports, __webpack_require__) { + 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 - /** - * 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(); - } + this.beginPath(); + this.moveTo(xe, ym); - // token types enumeration - var TOKENTYPE = { - NULL : 0, - DELIMITER : 1, - IDENTIFIER: 2, - UNKNOWN : 3 - }; + this.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); + this.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); - // map with all delimiters - var DELIMITERS = { - '{': true, - '}': true, - '[': true, - ']': true, - ';': true, - '=': true, - ',': true, + this.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); + this.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); - '->': true, - '--': true - }; + this.lineTo(xe, ymb); - 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.bezierCurveTo(xe, ymb + oy, xm + ox, yeb, xm, yeb); + this.bezierCurveTo(xm - ox, yeb, x, ymb + oy, x, ymb); - /** - * 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.lineTo(x, ym); + }; - /** - * 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); - } - /** - * Preview the next character from the dot file. - * @return {String} cNext - */ - function nextPreview() { - return dot.charAt(index + 1); - } + /** + * 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); - /** - * 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); - } + // 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); - /** - * 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 = {}; - } + // 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); - if (b) { - for (var name in b) { - if (b.hasOwnProperty(name)) { - a[name] = b[name]; - } - } - } - return a; - } + // 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); - /** - * 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; + 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; } - } + }; + + // TODO: add diamond shape } - /** - * 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; - // 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; - } +/***/ }, +/* 44 */ +/***/ function(module, exports, __webpack_require__) { - // 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; - } - } - } + var PhysicsMixin = __webpack_require__(55); + var ClusterMixin = __webpack_require__(49); + var SectorsMixin = __webpack_require__(50); + var SelectionMixin = __webpack_require__(51); + var ManipulationMixin = __webpack_require__(52); + var NavigationMixin = __webpack_require__(53); + var HierarchicalLayoutMixin = __webpack_require__(54); - if (!current) { - // this is a new node - current = { - id: node.id - }; - if (graph.node) { - // clone default attributes - current.attr = merge(current.attr, graph.node); + /** + * 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 node to this (sub)graph and all its parent graphs - for (i = graphs.length - 1; i >= 0; i--) { - var g = graphs[i]; - if (!g.nodes) { - g.nodes = []; - } - if (g.nodes.indexOf(current) == -1) { - g.nodes.push(current); + /** + * 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; } } + }; - // 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 + * Mixin the physics system and initialize the parameters required. + * + * @private */ - 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 + exports._loadPhysicsSystem = function () { + this._loadMixin(PhysicsMixin); + this._loadSelectedForceSolver(); + if (this.constants.configurePhysics == true) { + this._loadPhysicsConfiguration(); } - } + }; + /** - * 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 + * Mixin the cluster system and initialize the parameters required. + * + * @private */ - function createEdge(graph, from, to, type, attr) { - var edge = { - from: from, - to: to, - type: type - }; + exports._loadClusterSystem = function () { + this.clusterSession = 0; + this.hubThreshold = 5; + this._loadMixin(ClusterMixin); + }; - if (graph.edge) { - edge.attr = merge({}, graph.edge); // clone default attributes - } - edge.attr = merge(edge.attr || {}, attr); // merge attributes - return edge; - } + /** + * Mixin the sector system and initialize the parameters required + * + * @private + */ + 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._loadMixin(SectorsMixin); + }; + /** - * Get next token in the current dot file. - * The token and token type are available as token and tokenType + * Mixin the selection system and initialize the parameters required + * + * @private */ - function getToken() { - tokenType = TOKENTYPE.NULL; - token = ''; + exports._loadSelectionSystem = function () { + this.selectionObj = {nodes: {}, edges: {}}; - // skip over whitespaces - while (c == ' ' || c == '\t' || c == '\n' || c == '\r') { // space, tab, enter - next(); - } + this._loadMixin(SelectionMixin); + }; - do { - var isComment = false; - // skip comment - if (c == '#') { - // find the previous non-space character - var i = index - 1; - while (dot.charAt(i) == ' ' || dot.charAt(i) == '\t') { - i--; + /** + * Mixin the navigationUI (User Interface) system and initialize the parameters required + * + * @private + */ + 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"; } - 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; + else { + this.manipulationDiv.style.display = "none"; } + this.containerElement.insertBefore(this.manipulationDiv, this.frame); } - if (c == '/' && nextPreview() == '/') { - // skip line comment - while (c != '' && c != '\n') { - next(); + + 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"; } - 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(); - } + else { + this.editModeDiv.style.display = "block"; } - isComment = true; + this.containerElement.insertBefore(this.editModeDiv, this.frame); } - // skip over whitespaces - while (c == ' ' || c == '\t' || c == '\n' || c == '\r') { // space, tab, enter - next(); + 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); } - } - while (isComment); - - // check for end of dot file - if (c == '') { - // token is still empty - tokenType = TOKENTYPE.DELIMITER; - return; - } - - // check for delimiters consisting of 2 characters - var c2 = c + nextPreview(); - if (DELIMITERS[c2]) { - tokenType = TOKENTYPE.DELIMITER; - token = c2; - next(); - next(); - return; - } - - // 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(); + // load the manipulation functions + this._loadMixin(ManipulationMixin); - 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; + // 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); - // 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'); + this.manipulationDiv = undefined; + this.editModeDiv = undefined; + this.closeDiv = undefined; + // remove the mixin functions + this._clearMixin(ManipulationMixin); } - 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 + * Mixin the navigation (User Interface) system and initialize the parameters required + * + * @private */ - function parseGraph() { - var graph = {}; - - first(); - getToken(); + exports._loadNavigationControls = function () { + this._loadMixin(NavigationMixin); - // optional strict keyword - if (token == 'strict') { - graph.strict = true; - getToken(); + // the clean function removes the button divs, this is done to remove the bindings. + this._cleanNavigation(); + if (this.constants.navigation.enabled == true) { + this._loadNavigationElements(); } + }; - // graph or digraph keyword - if (token == 'graph' || token == 'digraph') { - graph.type = token; - getToken(); - } - // optional graph id - if (tokenType == TOKENTYPE.IDENTIFIER) { - graph.id = token; - getToken(); - } + /** + * Mixin the hierarchical layout system. + * + * @private + */ + exports._loadHierarchySystem = function () { + this._loadMixin(HierarchicalLayoutMixin); + }; - // open angle bracket - if (token != '{') { - throw newSyntaxError('Angle bracket { expected'); - } - getToken(); - // statements - parseStatements(graph); +/***/ }, +/* 45 */ +/***/ function(module, exports, __webpack_require__) { - // close angle bracket - if (token != '}') { - throw newSyntaxError('Angle bracket } expected'); - } - getToken(); + + /** + * Expose `Emitter`. + */ - // end of file - if (token !== '') { - throw newSyntaxError('End of file expected'); - } - getToken(); + module.exports = Emitter; - // remove temporary default properties - delete graph.node; - delete graph.edge; - delete graph.graph; + /** + * Initialize a new `Emitter`. + * + * @api public + */ - return graph; - } + function Emitter(obj) { + if (obj) return mixin(obj); + }; /** - * Parse a list with statements. - * @param {Object} graph + * Mixin the emitter properties. + * + * @param {Object} obj + * @return {Object} + * @api private */ - function parseStatements (graph) { - while (token !== '' && token != '}') { - parseStatement(graph); - if (token == ';') { - getToken(); - } + + function mixin(obj) { + for (var key in Emitter.prototype) { + obj[key] = Emitter.prototype[key]; } + return obj; } /** - * 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 + * Listen on the given `event` with `fn`. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public */ - 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); - } - } + Emitter.prototype.on = + Emitter.prototype.addEventListener = function(event, fn){ + this._callbacks = this._callbacks || {}; + (this._callbacks[event] = this._callbacks[event] || []) + .push(fn); + return this; + }; /** - * Parse a subgraph - * @param {Object} graph parent graph object - * @return {Object | null} subgraph + * Adds an `event` listener that will be invoked a single + * time then automatically removed. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public */ - function parseSubgraph (graph) { - var subgraph = null; - // optional subgraph keyword - if (token == 'subgraph') { - subgraph = {}; - subgraph.type = 'subgraph'; - getToken(); + Emitter.prototype.once = function(event, fn){ + var self = this; + this._callbacks = this._callbacks || {}; - // optional graph id - if (tokenType == TOKENTYPE.IDENTIFIER) { - subgraph.id = token; - getToken(); - } + function on() { + self.off(event, on); + fn.apply(this, arguments); } - // open angle bracket - if (token == '{') { - getToken(); + on.fn = fn; + this.on(event, on); + return this; + }; - if (!subgraph) { - subgraph = {}; - } - subgraph.parent = graph; - subgraph.node = graph.node; - subgraph.edge = graph.edge; - subgraph.graph = graph.graph; + /** + * Remove the given callback for `event` or all + * registered callbacks. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ - // statements - parseStatements(subgraph); + Emitter.prototype.off = + Emitter.prototype.removeListener = + Emitter.prototype.removeAllListeners = + Emitter.prototype.removeEventListener = function(event, fn){ + this._callbacks = this._callbacks || {}; - // close angle bracket - if (token != '}') { - throw newSyntaxError('Angle bracket } expected'); - } - getToken(); + // all + if (0 == arguments.length) { + this._callbacks = {}; + return this; + } - // remove temporary default properties - delete subgraph.node; - delete subgraph.edge; - delete subgraph.graph; - delete subgraph.parent; + // specific event + var callbacks = this._callbacks[event]; + if (!callbacks) return this; - // register at the parent graph - if (!graph.subgraphs) { - graph.subgraphs = []; - } - graph.subgraphs.push(subgraph); + // remove all handlers + if (1 == arguments.length) { + delete this._callbacks[event]; + return this; } - return subgraph; - } + // 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; + }; /** - * 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. + * Emit `event` with the given args. + * + * @param {String} event + * @param {Mixed} ... + * @return {Emitter} */ - 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(); + Emitter.prototype.emit = function(event){ + this._callbacks = this._callbacks || {}; + var args = [].slice.call(arguments, 1) + , callbacks = this._callbacks[event]; - // graph attributes - graph.graph = parseAttributeList(); - return 'graph'; + if (callbacks) { + callbacks = callbacks.slice(0); + for (var i = 0, len = callbacks.length; i < len; ++i) { + callbacks[i].apply(this, args); + } } - return null; - } + return this; + }; /** - * parse a node statement - * @param {Object} graph - * @param {String | Number} id + * Return array of callbacks for `event`. + * + * @param {String} event + * @return {Array} + * @api public */ - 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); - } + Emitter.prototype.listeners = function(event){ + this._callbacks = this._callbacks || {}; + return this._callbacks[event] || []; + }; /** - * Parse an edge or a series of edges - * @param {Object} graph - * @param {String | Number} from Id of the from node + * Check if this emitter has `event` handlers. + * + * @param {String} event + * @return {Boolean} + * @api public */ - 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(); + Emitter.prototype.hasListeners = function(event){ + return !! this.listeners(event).length; + }; - // create edge - var edge = createEdge(graph, from, to, type, attr); - addEdge(graph, edge); - from = to; - } - } +/***/ }, +/* 46 */ +/***/ function(module, exports, __webpack_require__) { /** - * Parse a set with attributes, - * for example [label="1.000", shape=solid] - * @return {Object | null} attr + * 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 */ - function parseAttributeList() { - var attr = null; - while (token == '[') { - getToken(); - attr = {}; - while (token !== '' && token != ']') { - if (tokenType != TOKENTYPE.IDENTIFIER) { - throw newSyntaxError('Attribute name expected'); - } - var name = token; + /** + * 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' + }, - getToken(); - if (token != '=') { - throw newSyntaxError('Equal sign = expected'); - } - getToken(); + /** + * 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: '\'' + }, - if (tokenType != TOKENTYPE.IDENTIFIER) { - throw newSyntaxError('Attribute value expected'); - } - var value = token; - setValue(attr, name, value); // name can be a path + /** + * 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', + '_': '-', + '+': '=', + ':': ';', + '\"': '\'', + '<': ',', + '>': '.', + '?': '/', + '|': '\\' + }, - getToken(); - if (token ==',') { - getToken(); - } - } + /** + * 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 (token != ']') { - throw newSyntaxError('Bracket ] expected'); - } - getToken(); - } + /** + * 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, - return attr; - } + /** + * a list of all the callbacks setup via Mousetrap.bind() + * + * @type {Object} + */ + _callbacks = {}, - /** - * 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 + ')'); - } + /** + * direct map of string combinations to callbacks used for trigger() + * + * @type {Object} + */ + _direct_map = {}, - /** - * 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) + '...'); - } + /** + * keeps track of what level each sequence is at since multiple + * sequences can start out with the same sequence + * + * @type {Object} + */ + _sequence_levels = {}, - /** - * 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); - } - } - } + /** + * variable to store the setTimeout call + * + * @type {null|number} + */ + _reset_timer, - /** - * 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: {} - }; + /** + * temporary state where we will ignore the next keyup + * + * @type {boolean|string} + */ + _ignore_next_keyup = false, - // 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); - }); + /** + * 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; } - // 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; - } + /** + * loop through to map numbers on the numeric keypad + */ + for (i = 0; i <= 9; ++i) { + _MAP[i + 96] = i; + } - dotData.edges.forEach(function (dotEdge) { - var from, to; - if (dotEdge.from instanceof Object) { - from = dotEdge.from.nodes; - } - else { - from = { - id: dotEdge.from - } + /** + * 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); } - if (dotEdge.to instanceof Object) { - to = dotEdge.to.nodes; + object.attachEvent('on' + type, callback); + } + + /** + * takes the event and returns the key character + * + * @param {Event} e + * @return {string} + */ + function _characterFromEvent(e) { + + // for keypress events we should return the character as is + if (e.type == 'keypress') { + return String.fromCharCode(e.which); } - else { - to = { - id: dotEdge.to - } + + // for non keypress events the special maps are needed + if (_MAP[e.which]) { + return _MAP[e.which]; } - if (dotEdge.from instanceof Object && dotEdge.from.edges) { - dotEdge.from.edges.forEach(function (subEdge) { - var graphEdge = convertEdge(subEdge); - graphData.edges.push(graphEdge); - }); + if (_KEYCODE_MAP[e.which]) { + return _KEYCODE_MAP[e.which]; } - 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 it is not in the special map + return String.fromCharCode(e.which).toLowerCase(); + } - if (dotEdge.to instanceof Object && dotEdge.to.edges) { - dotEdge.to.edges.forEach(function (subEdge) { - var graphEdge = convertEdge(subEdge); - graphData.edges.push(graphEdge); - }); + /** + * 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; + + // if the element has the class "mousetrap" then no need to stop + if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) { + return false; } - }); - } - // copy the options - if (dotData.attr) { - graphData.options = dotData.attr; + // stop for input, select, and textarea + return tag_name == 'INPUT' || tag_name == 'SELECT' || tag_name == 'TEXTAREA' || (element.contentEditable && element.contentEditable == 'true'); } - return graphData; - } - - // exports - exports.parseDOT = parseDOT; - exports.DOTToGraph = DOTToGraph; + /** + * 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 || {}; -/***/ }, -/* 44 */ -/***/ function(module, exports, __webpack_require__) { + var active_sequences = false, + key; - - function parseGephi(gephiJSON, options) { - var edges = []; - var nodes = []; - this.options = { - edges: { - inheritColor: true - }, - nodes: { - allowedToMove: false, - parseColor: false - } - }; + for (key in _sequence_levels) { + if (do_not_reset[key]) { + active_sequences = true; + continue; + } + _sequence_levels[key] = 0; + } - if (options !== undefined) { - this.options.nodes['allowedToMove'] = options.allowedToMove | false; - this.options.nodes['parseColor'] = options.parseColor | false; - this.options.edges['inheritColor'] = options.inheritColor | true; + if (!active_sequences) { + _inside_sequence = false; + } } - 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); - } + /** + * 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 = []; - 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); - } + // if there are no events related to this keycode + if (!_callbacks[character]) { + return []; + } - return {nodes:nodes, edges:edges}; - } + // if a modifier key is coming up on its own we should allow it + if (action == 'keyup' && _isModifier(character)) { + modifiers = [character]; + } - exports.parseGephi = parseGephi; + // 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]; -/***/ }, -/* 45 */ -/***/ function(module, exports, __webpack_require__) { + // 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; + } - var util = __webpack_require__(1); + // if the action we are looking for doesn't match the action we got + // then we should keep going + if (action != callback.action) { + continue; + } - /** - * @class Groups - * This class can store groups and properties specific for groups. - */ - function Groups() { - this.clear(); - this.defaultIndex = 0; - } + // 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)) { + // 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); + } - /** - * default constants for group colors - */ - 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 - ]; + matches.push(callback); + } + } + return matches; + } - /** - * 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++; + /** + * 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'); } - } - return i; - } - }; + if (e.altKey) { + modifiers.push('alt'); + } - /** - * 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; + if (e.ctrlKey) { + modifiers.push('ctrl'); + } + + if (e.metaKey) { + modifiers.push('meta'); + } + + return modifiers; } - return group; - }; + /** + * 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(); + } - /** - * Add a custom group style - * @param {String} groupname - * @param {Object} style An object containing borderColor, - * backgroundColor, etc. - * @return {Object} group The created group object - */ - Groups.prototype.add = function (groupname, style) { - this.groups[groupname] = style; - if (style.color) { - style.color = util.parseColor(style.color); + if (e.stopPropagation) { + e.stopPropagation(); + } + + e.returnValue = false; + e.cancelBubble = true; + } } - return style; - }; - module.exports = Groups; + /** + * handles a character key event + * + * @param {string} character + * @param {Event} e + * @returns void + */ + function _handleCharacter(character, e) { + // if this event should not happen stop here + if (_stop(e)) { + return; + } -/***/ }, -/* 46 */ -/***/ function(module, exports, __webpack_require__) { + var callbacks = _getMatches(character, _eventModifiers(e), e.type), + i, + do_not_reset = {}, + processed_sequence_callback = false; - /** - * @class Images - * This class loads images and keeps them stored. - */ - function Images() { - this.images = {}; + // loop through matching callbacks for this key event + for (i = 0; i < callbacks.length; ++i) { - this.callback = undefined; - } + // 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; - /** - * 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; - }; + // keep a list of which sequences were matches for later + do_not_reset[callbacks[i].seq] = 1; + _fireCallback(callbacks[i].callback, e); + continue; + } - /** - * - * @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); + // 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); } - }; - img.src = url; } - return img; - }; + /** + * handles a keydown event + * + * @param {Event} e + * @returns void + */ + function _handleKey(e) { - module.exports = Images; + // 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; + var character = _characterFromEvent(e); -/***/ }, -/* 47 */ -/***/ function(module, exports, __webpack_require__) { + // no character found then stop + if (!character) { + return; + } - var util = __webpack_require__(1); + if (e.type == 'keyup' && _ignore_next_keyup == character) { + _ignore_next_keyup = false; + return; + } - /** - * @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 - * - */ - function Node(properties, imagelist, grouplist, constants) { - this.selected = false; - this.hover = false; + _handleCharacter(character, e); + } - this.edges = []; // all edges connected to this node - this.dynamicEdges = []; - this.reroutedEdges = {}; + /** + * 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'; + } - this.group = constants.nodes.group; - this.fontSize = Number(constants.nodes.fontSize); - this.fontFace = constants.nodes.fontFace; - this.fontColor = constants.nodes.fontColor; - this.fontDrawThreshold = 3; - - this.color = constants.nodes.color; - - // set defaults for the properties - this.id = undefined; - this.shape = constants.nodes.shape; - this.image = constants.nodes.image; - 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.radius = constants.nodes.radius; - this.baseRadiusValue = constants.nodes.radius; - this.radiusFixed = false; - this.radiusMin = constants.nodes.radiusMin; - this.radiusMax = constants.nodes.radiusMax; - this.level = -1; - this.preassignedLevel = false; - this.borderWidth = constants.nodes.borderWidth; - this.borderWidthSelected = constants.nodes.borderWidthSelected; - - - this.imagelist = imagelist; - this.grouplist = grouplist; + /** + * 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); + } - // 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.minForce = constants.minForce; - this.damping = constants.physics.damping; - this.mass = 1; // kg - this.fixedData = {x:null,y:null}; + /** + * 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; + } - this.setProperties(properties, constants); + if (_MAP.hasOwnProperty(key)) { + _REVERSE_MAP[_MAP[key]] = key; + } + } + } + return _REVERSE_MAP; + } - // creating the variables for clustering - this.resetCluster(); - this.dynamicEdgesLength = 0; - this.clusterSession = 0; - this.clusterSizeWidthFactor = constants.clustering.nodeScaling.width; - this.clusterSizeHeightFactor = constants.clustering.nodeScaling.height; - this.clusterSizeRadiusFactor = constants.clustering.nodeScaling.radius; - this.maxNodeSizeIncrements = constants.clustering.maxNodeSizeIncrements; - this.growthIndicator = 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) { - // 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; - } + // 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'; + } - /** - * (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 = []; - }; + // modifier keys don't work as expected with keypress, + // switch to keydown + if (action == 'keypress' && modifiers.length) { + action = 'keydown'; + } - /** - * 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); + return action; } - this.dynamicEdgesLength = this.dynamicEdges.length; - }; - /** - * 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; - }; + /** + * 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; - /** - * 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; - } - 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.group !== undefined) {this.group = properties.group;} - 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;} - if (properties.borderWidth !== undefined) {this.borderWidth = properties.borderWidth;} - if (properties.borderWidthSelected !== undefined) {this.borderWidthSelected = properties.borderWidthSelected;} + // if there is no action pick the best one for the first key + // in the sequence + if (!action) { + action = _pickBestAction(keys[0], []); + } - // physics - if (properties.mass !== undefined) {this.mass = properties.mass;} + /** + * 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(); + }, - // 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;} + /** + * 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 (this.id === undefined) { - throw "Node must have an id"; - } + // 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); + } - // copy group properties - if (this.group !== undefined && this.group != "") { - var groupObj = this.grouplist.get(this.group); - for (var prop in groupObj) { - if (groupObj.hasOwnProperty(prop)) { - this[prop] = groupObj[prop]; + // 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); } - } } - // individual shape properties - if (properties.shape !== undefined) {this.shape = properties.shape;} - if (properties.image !== undefined) {this.image = properties.image;} - if (properties.radius !== undefined) {this.radius = properties.radius; this.baseRadiusValue = this.radius;} - if (properties.color !== undefined) {this.color = util.parseColor(properties.color);} + /** + * 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) { - if (properties.fontColor !== undefined) {this.fontColor = properties.fontColor;} - if (properties.fontSize !== undefined) {this.fontSize = properties.fontSize;} - if (properties.fontFace !== undefined) {this.fontFace = properties.fontFace;} + // make sure multiple spaces in a row become a single space + combination = combination.replace(/\s+/g, ' '); - if (this.image !== undefined && this.image != "") { - if (this.imagelist) { - this.imageObj = this.imagelist.load(this.image); - } - else { - throw "No imagelist provided"; - } - } + var sequence = combination.split(' '), + i, + key, + keys, + modifiers = []; - 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 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); + } - if (this.shape == 'image') { - this.radiusMin = constants.nodes.widthMin; - this.radiusMax = constants.nodes.widthMax; - } + // take the keys from this pattern and figure out what the actual + // pattern is all about + keys = combination === '+' ? ['+'] : combination.split('+'); - // choose draw method depending on the shape - switch (this.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(); - }; + for (i = 0; i < keys.length; ++i) { + key = keys[i]; - /** - * select this node - */ - Node.prototype.select = function() { - this.selected = true; - this._reset(); - }; + // normalize key names + if (_SPECIAL_ALIASES[key]) { + key = _SPECIAL_ALIASES[key]; + } - /** - * unselect this node - */ - Node.prototype.unselect = function() { - this.selected = false; - this._reset(); - }; + // 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'); + } + // if this key is a modifier then add it to the list of modifiers + if (_isModifier(key)) { + modifiers.push(key); + } + } - /** - * Reset the calculated size of the node, forces it to recalculate its size - */ - Node.prototype.clearSizeCache = function() { - this._reset(); - }; + // depending on what the key combination is + // we will try to pick the best event for it + action = _pickBestAction(key, modifiers, action); - /** - * Reset the calculated size of the node, forces it to recalculate its size - * @private - */ - Node.prototype._reset = function() { - this.width = undefined; - this.height = undefined; - }; + // make sure to initialize array if this is the first time + // a callback is added for this key + if (!_callbacks[key]) { + _callbacks[key] = []; + } - /** - * 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; - }; + // remove an existing match if there is one + _getMatches(key, modifiers, action, !sequence_name, combination); - /** - * 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; + // 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 + }); + } - if (!this.width) { - this.resize(ctx); + /** + * 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); + } } - switch (this.shape) { - case 'circle': - case 'dot': - return this.radius + borderWidth; + // start! + _addEvent(document, 'keypress', _handleKey); + _addEvent(document, 'keydown', _handleKey); + _addEvent(document, 'keyup', _handleKey); - 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); + var mousetrap = { - // TODO: implement distanceToBorder for database - // TODO: implement distanceToBorder for triangle - // TODO: implement distanceToBorder for triangleDown + /** + * 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; + }, - 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; + /** + * 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; } + }; - } - // TODO: implement calculation of distance to border for all shapes - }; + module.exports = mousetrap; - /** - * 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; - }; - - /** - * 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; - }; - /** - * 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.mass; // acceleration - this.vx += ax * interval; // velocity - this.x += this.vx * interval; // position - } - if (!this.yFixed) { - var dy = this.damping * this.vy; // damping force - var ay = (this.fy - dy) / this.mass; // acceleration - this.vy += ay * interval; // velocity - this.y += this.vy * interval; // position - } - }; +/***/ }, +/* 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) { - /** - * 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.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; - } + /************************************ + Constants + ************************************/ - if (!this.yFixed) { - var dy = this.damping * this.vy; // damping force - var ay = (this.fy - dy) / this.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; - } - }; + 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, - /** - * 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); - }; + YEAR = 0, + MONTH = 1, + DATE = 2, + HOUR = 3, + MINUTE = 4, + SECOND = 5, + MILLISECOND = 6, - /** - * 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); - }; + // internal storage for language config files + languages = {}, - /** - * check if this node is selecte - * @return {boolean} selected True if node is selected, else false - */ - Node.prototype.isSelected = function() { - return this.selected; - }; + // 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 + }, - /** - * Retrieve the value of the node. Can be undefined - * @return {Number} value - */ - Node.prototype.getValue = function() { - return this.value; - }; + // check for nodeJS + hasModule = (typeof module !== 'undefined' && module.exports), - /** - * 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); - }; + // ASP.NET json date format regex + aspNetJsonRegex = /^\/?Date\((\-?\d+)/i, + aspNetTimeSpanJsonRegex = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/, + // 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)$/, - /** - * 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.radius = (this.radiusMin + this.radiusMax) / 2; - } - else { - var scale = (this.radiusMax - this.radiusMin) / (max - min); - this.radius = (this.value - min) * scale + this.radiusMin; - } - } - this.baseRadiusValue = this.radius; - }; + // 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, - /** - * 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"; - }; + // 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}/, - /** - * 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"; - }; + //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 - /** - * 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); - }; + // 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)?)?$/, - Node.prototype._resizeImage = function (ctx) { - // TODO: pre calculate the image size + isoFormat = 'YYYY-MM-DDTHH:mm:ssZ', - if (!this.width || !this.height) { // undefined or 0 - var width, height; - if (this.value) { - this.radius = this.baseRadiusValue; - var scale = this.imageObj.height / this.imageObj.width; - if (scale !== undefined) { - width = this.radius || this.imageObj.width; - height = this.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; + 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}/] + ], - 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.radius += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeRadiusFactor; - this.growthIndicator = this.width - width; - } - } - - }; - - Node.prototype._drawImage = function (ctx) { - this._resizeImage(ctx); - - this.left = this.x - this.width / 2; - this.top = this.y - this.height / 2; - - 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); - - ctx.globalAlpha = 0.5; - ctx.drawImage(this.imageObj, this.left - lineWidth, this.top - lineWidth, this.width + 2*lineWidth, this.height + 2*lineWidth); - } + // 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/] + ], - // 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; - } + // timezone chunker "+10:00" > ["10", "00"] or "-1530" > ["-15", "30"] + parseTimezoneChunker = /([\+\-]|\d\d)/gi, - this._label(ctx, this.label, this.x, yLabel, undefined, "top"); - }; + // 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 + }, + 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' + }, - 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; + camelFunctions = { + dayofyear : 'dayOfYear', + isoweekday : 'isoWeekday', + isoweek : 'isoWeek', + weekyear : 'weekYear', + isoweekyear : 'isoWeekYear' + }, - 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.radius += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeRadiusFactor; + // format function strings + formatFunctions = {}, - } - }; + // 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 + }, - Node.prototype._drawBox = function (ctx) { - this._resizeBox(ctx); + // tokens to ordinalize and pad + ordinalizeTokens = 'DDD w W M D d'.split(' '), + paddedTokens = 'M D H h m s w W'.split(' '), - this.left = this.x - this.width / 2; - this.top = this.y - this.height / 2; + 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(); + } + }, - var clusterLineWidth = 2.5; - var borderWidth = this.borderWidth; - var selectionLineWidth = this.borderWidthSelected || 2 * this.borderWidth; + lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin']; - ctx.strokeStyle = this.selected ? this.color.highlight.border : this.hover ? this.color.hover.border : this.color.border; + // 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"); + } + } - // 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); + 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 + }; + } - ctx.roundRect(this.left-2*ctx.lineWidth, this.top-2*ctx.lineWidth, this.width+4*ctx.lineWidth, this.height+4*ctx.lineWidth, this.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); + 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); + } - ctx.fillStyle = this.selected ? this.color.highlight.background : this.color.background; + 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); + }; + } - ctx.roundRect(this.left, this.top, this.width, this.height, this.radius); - ctx.fill(); - ctx.stroke(); + 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); + } + formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3); - this._label(ctx, this.label, this.x, this.y); - }; + /************************************ + Constructors + ************************************/ - 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; + function Language() { - // 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.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; + // Moment prototype object + function Moment(config) { + checkOverflow(config); + extend(this, config); + } - var clusterLineWidth = 2.5; - var borderWidth = this.borderWidth; - var selectionLineWidth = this.borderWidthSelected || 2 * this.borderWidth; + // 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; - ctx.strokeStyle = this.selected ? this.color.highlight.border : this.hover ? this.color.hover.border : this.color.border; + // 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; - // 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._data = {}; - 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); + this._bubble(); + } - ctx.fillStyle = this.selected ? this.color.highlight.background : this.hover ? this.color.hover.background : this.color.background; - ctx.database(this.x - this.width/2, this.y - this.height*0.5, this.width, this.height); - ctx.fill(); - ctx.stroke(); + /************************************ + Helpers + ************************************/ - this._label(ctx, this.label, this.x, this.y); - }; + function extend(a, b) { + for (var i in b) { + if (b.hasOwnProperty(i)) { + a[i] = b[i]; + } + } - 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.radius = diameter / 2; + if (b.hasOwnProperty("toString")) { + a.toString = b.toString; + } - this.width = diameter; - this.height = diameter; + if (b.hasOwnProperty("valueOf")) { + a.valueOf = b.valueOf; + } - // 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.radius += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeRadiusFactor; - this.growthIndicator = this.radius - 0.5*diameter; - } - }; + return a; + } - Node.prototype._drawCircle = function (ctx) { - this._resizeCircle(ctx); - this.left = this.x - this.width / 2; - this.top = this.y - this.height / 2; + function cloneMoment(m) { + var result = {}, i; + for (i in m) { + if (m.hasOwnProperty(i) && momentProperties.hasOwnProperty(i)) { + result[i] = m[i]; + } + } - var clusterLineWidth = 2.5; - var borderWidth = this.borderWidth; - var selectionLineWidth = this.borderWidthSelected || 2 * this.borderWidth; + return result; + } - ctx.strokeStyle = this.selected ? this.color.highlight.border : this.hover ? this.color.hover.border : this.color.border; + function absRound(number) { + if (number < 0) { + return Math.ceil(number); + } else { + return Math.floor(number); + } + } - // 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); + // 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; - ctx.circle(this.x, this.y, this.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); + while (output.length < targetLength) { + output = '0' + output; + } + return (sign ? (forceSign ? '+' : '') : '-') + output; + } - ctx.fillStyle = this.selected ? this.color.highlight.background : this.hover ? this.color.hover.background : this.color.background; - ctx.circle(this.x, this.y, this.radius); - ctx.fill(); - ctx.stroke(); + // 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; - this._label(ctx, this.label, this.x, this.y); - }; + 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); + } + } - Node.prototype._resizeEllipse = function (ctx) { - if (!this.width) { - var textSize = this.getTextSize(ctx); + // check if is an array + function isArray(input) { + return Object.prototype.toString.call(input) === '[object Array]'; + } - this.width = textSize.width * 1.5; - this.height = textSize.height * 2; - if (this.width < this.height) { - this.width = this.height; + function isDate(input) { + return Object.prototype.toString.call(input) === '[object Date]' || + input instanceof Date; } - var defaultSize = this.width; - - // 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.radius += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeRadiusFactor; - this.growthIndicator = this.width - defaultSize; - } - }; - Node.prototype._drawEllipse = function (ctx) { - this._resizeEllipse(ctx); - this.left = this.x - this.width / 2; - this.top = this.y - this.height / 2; + // 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; + } - var clusterLineWidth = 2.5; - var borderWidth = this.borderWidth; - var selectionLineWidth = this.borderWidthSelected || 2 * this.borderWidth; + function normalizeUnits(units) { + if (units) { + var lowered = units.toLowerCase().replace(/(.)s$/, '$1'); + units = unitAliases[units] || camelFunctions[lowered] || lowered; + } + return units; + } - ctx.strokeStyle = this.selected ? this.color.highlight.border : this.hover ? this.color.hover.border : this.color.border; + function normalizeObjectUnits(inputObject) { + var normalizedInput = {}, + normalizedProp, + prop; - // 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); + for (prop in inputObject) { + if (inputObject.hasOwnProperty(prop)) { + normalizedProp = normalizeUnits(prop); + if (normalizedProp) { + normalizedInput[normalizedProp] = inputObject[prop]; + } + } + } - 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 normalizedInput; + } - ctx.fillStyle = this.selected ? this.color.highlight.background : this.hover ? this.color.hover.background : this.color.background; + function makeList(field) { + var count, setter; - ctx.ellipse(this.left, this.top, this.width, this.height); - ctx.fill(); - ctx.stroke(); - this._label(ctx, this.label, this.x, this.y); - }; + if (field.indexOf('week') === 0) { + count = 7; + setter = 'day'; + } + else if (field.indexOf('month') === 0) { + count = 12; + setter = 'month'; + } + else { + return; + } - Node.prototype._drawDot = function (ctx) { - this._drawShape(ctx, 'circle'); - }; + moment[field] = function (format, index) { + var i, getter, + method = moment.fn._lang[field], + results = []; - Node.prototype._drawTriangle = function (ctx) { - this._drawShape(ctx, 'triangle'); - }; + if (typeof format === 'number') { + index = format; + format = undefined; + } - Node.prototype._drawTriangleDown = function (ctx) { - this._drawShape(ctx, 'triangleDown'); - }; + getter = function (i) { + var m = moment().utc().set(setter, i); + return method.call(moment.fn._lang, m, format || ''); + }; - Node.prototype._drawSquare = function (ctx) { - this._drawShape(ctx, 'square'); - }; + if (index != null) { + return getter(index); + } + else { + for (i = 0; i < count; i++) { + results.push(getter(i)); + } + return results; + } + }; + } - Node.prototype._drawStar = function (ctx) { - this._drawShape(ctx, 'star'); - }; + function toInt(argumentForCoercion) { + var coercedNumber = +argumentForCoercion, + value = 0; - Node.prototype._resizeShape = function (ctx) { - if (!this.width) { - this.radius = this.baseRadiusValue; - var size = 2 * this.radius; - this.width = size; - this.height = size; + if (coercedNumber !== 0 && isFinite(coercedNumber)) { + if (coercedNumber >= 0) { + value = Math.floor(coercedNumber); + } else { + value = Math.ceil(coercedNumber); + } + } - // 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.radius += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeRadiusFactor; - this.growthIndicator = this.width - size; - } - }; + return value; + } - Node.prototype._drawShape = function (ctx, shape) { - this._resizeShape(ctx); + function daysInMonth(year, month) { + return new Date(Date.UTC(year, month + 1, 0)).getUTCDate(); + } - this.left = this.x - this.width / 2; - this.top = this.y - this.height / 2; + function weeksInYear(year, dow, doy) { + return weekOfYear(moment([year, 11, 31 + dow - doy]), dow, doy).week; + } - var clusterLineWidth = 2.5; - var borderWidth = this.borderWidth; - var selectionLineWidth = this.borderWidthSelected || 2 * this.borderWidth; - var radiusMultiplier = 2; + function daysInYear(year) { + return isLeapYear(year) ? 366 : 365; + } - // 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; - } + function isLeapYear(year) { + return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; + } - ctx.strokeStyle = this.selected ? this.color.highlight.border : this.hover ? this.color.hover.border : this.color.border; + 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; - // 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 (m._pf._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) { + overflow = DATE; + } - ctx[shape](this.x, this.y, this.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); + m._pf.overflow = overflow; + } + } - ctx.fillStyle = this.selected ? this.color.highlight.background : this.hover ? this.color.hover.background : this.color.background; - ctx[shape](this.x, this.y, this.radius); - ctx.fill(); - ctx.stroke(); + 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 (this.label) { - this._label(ctx, this.label, this.x, this.y + this.height / 2, undefined, 'top',true); - } - }; + if (m._strict) { + m._isValid = m._isValid && + m._pf.charsLeftOver === 0 && + m._pf.unusedTokens.length === 0; + } + } + return m._isValid; + } - 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; + function normalizeLanguage(key) { + return key ? key.toLowerCase().replace('_', '-') : key; + } - // 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.radius += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeRadiusFactor; - this.growthIndicator = this.width - (textSize.width + 2 * margin); - } - }; + // 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(); + } - Node.prototype._drawText = function (ctx) { - this._resizeText(ctx); - this.left = this.x - this.width / 2; - this.top = this.y - this.height / 2; - - this._label(ctx, this.label, this.x, this.y); - }; + /************************************ + Languages + ************************************/ - Node.prototype._label = function (ctx, text, x, y, align, baseline, labelUnderNode) { - if (text && this.fontSize * this.networkScale > this.fontDrawThreshold) { - ctx.font = (this.selected ? "bold " : "") + this.fontSize + "px " + this.fontFace; - ctx.fillStyle = this.fontColor || "black"; - ctx.textAlign = align || "center"; - ctx.textBaseline = baseline || "middle"; + extend(Language.prototype, { - var lines = text.split('\n'); - var lineCount = lines.length; - var fontSize = (this.fontSize + 4); - var yLine = y + (1 - lineCount) / 2 * fontSize; - if (labelUnderNode == true) { - yLine = y + (1 - lineCount) / (2 * fontSize); - } + 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 i = 0; i < lineCount; i++) { - ctx.fillText(lines[i], x, yLine); - yLine += fontSize; - } - } - }; + _months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"), + months : function (m) { + return this._months[m.month()]; + }, + _monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"), + monthsShort : function (m) { + return this._monthsShort[m.month()]; + }, - Node.prototype.getTextSize = function(ctx) { - if (this.label !== undefined) { - ctx.font = (this.selected ? "bold " : "") + this.fontSize + "px " + this.fontFace; + monthsParse : function (monthName) { + var i, mom, regex; - var lines = this.label.split('\n'), - height = (this.fontSize + 4) * lines.length, - width = 0; + if (!this._monthsParse) { + this._monthsParse = []; + } - for (var i = 0, iMax = lines.length; i < iMax; i++) { - width = Math.max(width, ctx.measureText(lines[i]).width); - } + 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; + } + } + }, - return {"width": width, "height": height}; - } - else { - return {"width": 0, "height": 0}; - } - }; + _weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"), + weekdays : function (m) { + return this._weekdays[m.day()]; + }, - /** - * 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} - */ - 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; - } - }; + _weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"), + weekdaysShort : function (m) { + return this._weekdaysShort[m.day()]; + }, - /** - * checks if the core of the node is in the display area, this is used for opening clusters around zoom - * @returns {boolean} - */ - 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); - }; + _weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"), + weekdaysMin : function (m) { + return this._weekdaysMin[m.day()]; + }, - /** - * 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; - }; + weekdaysParse : function (weekdayName) { + var i, mom, regex; + if (!this._weekdaysParse) { + this._weekdaysParse = []; + } - /** - * This allows the zoom level of the network to influence the rendering - * - * @param scale - */ - Node.prototype.setScale = function(scale) { - this.networkScaleInv = 1.0/scale; - this.networkScale = 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; + } + } + }, + _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'); + }, - /** - * 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; - }; + _meridiemParse : /[ap]\.?m?\.?/i, + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'pm' : 'PM'; + } else { + return isLower ? '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 (key, mom) { + var output = this._calendar[key]; + return typeof output === 'function' ? output.apply(mom) : output; + }, - /** - * Basic preservation of (kinectic) energy - * - * @param massBeforeClustering - */ - Node.prototype.updateVelocity = function(massBeforeClustering) { - var energyBefore = this.vx * this.vx * massBeforeClustering; - //this.vx = (this.vx < 0) ? -Math.sqrt(energyBefore/this.mass) : Math.sqrt(energyBefore/this.mass); - this.vx = Math.sqrt(energyBefore/this.mass); - energyBefore = this.vy * this.vy * massBeforeClustering; - //this.vy = (this.vy < 0) ? -Math.sqrt(energyBefore/this.mass) : Math.sqrt(energyBefore/this.mass); - this.vy = Math.sqrt(energyBefore/this.mass); - }; + _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); + }, - module.exports = Node; + ordinal : function (number) { + return this._ordinal.replace("%d", number); + }, + _ordinal : "%d", + preparse : function (string) { + return string; + }, -/***/ }, -/* 48 */ -/***/ function(module, exports, __webpack_require__) { - - var util = __webpack_require__(1); - var Node = __webpack_require__(47); + postformat : function (string) { + return string; + }, - /** - * @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 Edge (properties, network, constants) { - if (!network) { - throw "No network provided"; - } - this.network = network; + week : function (mom) { + return weekOfYear(mom, this._week.dow, this._week.doy).week; + }, - // initialize constants - this.widthMin = constants.edges.widthMin; - this.widthMax = constants.edges.widthMax; + _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. + }, - // initialize variables - this.id = undefined; - this.fromId = undefined; - this.toId = undefined; - this.style = constants.edges.style; - this.title = undefined; - this.width = constants.edges.width; - this.widthSelectionMultiplier = constants.edges.widthSelectionMultiplier; - this.widthSelected = this.width * this.widthSelectionMultiplier; - this.hoverWidth = constants.edges.hoverWidth; - this.value = undefined; - this.length = constants.physics.springLength; - this.customLength = false; - this.selected = false; - this.hover = false; - this.smoothCurves = constants.smoothCurves; - this.dynamicSmoothCurves = constants.dynamicSmoothCurves; - this.arrowScaleFactor = constants.edges.arrowScaleFactor; - this.inheritColor = constants.edges.inheritColor; + _invalidDate: 'Invalid date', + invalidDate: function () { + return this._invalidDate; + } + }); - this.from = null; // a node - this.to = null; // a node - this.via = null; // a temp node + // 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]; + } - // 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 = []; + // Remove a language from the `languages` cache. Mostly useful in tests. + function unloadLang(key) { + delete languages[key]; + } - this.connected = false; + // 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__(56)("./" + k); + } catch (e) { } + } + return languages[k]; + }; - // Added to support dashed lines - // David Jordan - // 2012-08-08 - this.dash = util.extend({}, constants.edges.dash); // contains properties length, gap, altLength + if (!key) { + return moment.fn._lang; + } - this.color = {color:constants.edges.color.color, - highlight:constants.edges.color.highlight, - hover:constants.edges.color.hover}; - this.widthFixed = false; - this.lengthFixed = false; + if (!isArray(key)) { + //short-circuit everything else + lang = get(key); + if (lang) { + return lang; + } + key = [key]; + } - this.setProperties(properties, constants); + //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; + } - this.controlNodesEnabled = false; - this.controlNodes = {from:null, to:null, positions:{}}; - this.connectedNode = null; - } + /************************************ + Formatting + ************************************/ - /** - * 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, constants) { - if (!properties) { - return; - } - if (properties.from !== undefined) {this.fromId = properties.from;} - if (properties.to !== undefined) {this.toId = properties.to;} + function removeFormattingTokens(input) { + if (input.match(/\[[\s\S]/)) { + return input.replace(/^\[|\]$/g, ""); + } + return input.replace(/\\/g, ""); + } - if (properties.id !== undefined) {this.id = properties.id;} - if (properties.style !== undefined) {this.style = properties.style;} - if (properties.label !== undefined) {this.label = properties.label;} + function makeFormatFunction(format) { + var array = format.match(formattingTokens), i, length; - if (this.label) { - this.fontSize = constants.edges.fontSize; - this.fontFace = constants.edges.fontFace; - this.fontColor = constants.edges.fontColor; - this.fontFill = constants.edges.fontFill; + 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 (properties.fontColor !== undefined) {this.fontColor = properties.fontColor;} - if (properties.fontSize !== undefined) {this.fontSize = properties.fontSize;} - if (properties.fontFace !== undefined) {this.fontFace = properties.fontFace;} - if (properties.fontFill !== undefined) {this.fontFill = properties.fontFill;} - } + 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 (properties.title !== undefined) {this.title = properties.title;} - if (properties.width !== undefined) {this.width = properties.width;} - if (properties.widthSelectionMultiplier !== undefined) - {this.widthSelectionMultiplier = properties.widthSelectionMultiplier;} - if (properties.hoverWidth !== undefined) {this.hoverWidth = properties.hoverWidth;} - if (properties.value !== undefined) {this.value = properties.value;} - if (properties.length !== undefined) {this.length = properties.length; - this.customLength = true;} + // format date using native date object + function formatMoment(m, format) { - // scale the arrow - if (properties.arrowScaleFactor !== undefined) {this.arrowScaleFactor = properties.arrowScaleFactor;} + if (!m.isValid()) { + return m.lang().invalidDate(); + } - if (properties.inheritColor !== undefined) {this.inheritColor = properties.inheritColor;} + format = expandFormat(format, m.lang()); - // Added to support dashed lines - // David Jordan - // 2012-08-08 - if (properties.dash) { - if (properties.dash.length !== undefined) {this.dash.length = properties.dash.length;} - if (properties.dash.gap !== undefined) {this.dash.gap = properties.dash.gap;} - if (properties.dash.altLength !== undefined) {this.dash.altLength = properties.dash.altLength;} - } + if (!formatFunctions[format]) { + formatFunctions[format] = makeFormatFunction(format); + } - if (properties.color !== undefined) { - if (util.isString(properties.color)) { - this.color.color = properties.color; - this.color.highlight = properties.color; - } - else { - if (properties.color.color !== undefined) {this.color.color = properties.color.color;} - if (properties.color.highlight !== undefined) {this.color.highlight = properties.color.highlight;} - if (properties.color.hover !== undefined) {this.color.hover = properties.color.hover;} + return formatFunctions[format](m); } - } - // A node is connected when it has a from and to node. - this.connect(); + function expandFormat(format, lang) { + var i = 5; - this.widthFixed = this.widthFixed || (properties.width !== undefined); - this.lengthFixed = this.lengthFixed || (properties.length !== undefined); + function replaceLongDateFormatTokens(input) { + return lang.longDateFormat(input) || input; + } - this.widthSelected = this.width * this.widthSelectionMultiplier; + localFormattingTokens.lastIndex = 0; + while (i >= 0 && localFormattingTokens.test(format)) { + format = format.replace(localFormattingTokens, replaceLongDateFormatTokens); + localFormattingTokens.lastIndex = 0; + i -= 1; + } - // set draw method based on style - switch (this.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; - } - }; - - /** - * Connect an edge to its nodes - */ - 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); + return format; } - } - }; - - /** - * Disconnect an edge from its nodes - */ - 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. - */ - Edge.prototype.getTitle = function() { - return typeof this.title === "function" ? this.title() : this.title; - }; + /************************************ + Parsing + ************************************/ - /** - * Retrieve the value of the edge. Can be undefined - * @return {Number} value - */ - 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 - */ - Edge.prototype.setValueRange = function(min, max) { - if (!this.widthFixed && this.value !== undefined) { - var scale = (this.widthMax - this.widthMin) / (max - min); - this.width = (this.value - min) * scale + this.widthMin; - this.widthSelected = this.width * this.widthSelectionMultiplier; - } - }; + // 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; + } + } - /** - * 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"; - }; + 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]); - /** - * 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; + return parts[0] === '+' ? -minutes : minutes; + } - var dist = this._getDistanceToEdge(xFrom, yFrom, xTo, yTo, xObj, yObj); + // function to convert string input to date + function addTimeToArrayFromToken(token, input, config) { + var a, datePartArray = config._a; - return (dist < distMax); - } - else { - return false - } - }; + 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); + } - Edge.prototype._getColor = function() { - var colorObj = this.color; - if (this.inheritColor == "to") { - colorObj = { - highlight: this.to.color.highlight.border, - hover: this.to.color.hover.border, - color: this.to.color.border - }; - } - else if (this.inheritColor == "from" || this.inheritColor == true) { - colorObj = { - highlight: this.from.color.highlight.border, - hover: this.from.color.hover.border, - color: this.from.color.border - }; - } + 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.selected == true) {return colorObj.highlight;} - else if (this.hover == true) {return colorObj.hover;} - else {return colorObj.color;} - } + 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; - /** - * 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(); + // 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; - if (this.from != this.to) { - // draw line - var via = this._line(ctx); + weekYear = dfl(w.gg, config._a[YEAR], weekOfYear(moment(), dow, doy).year); + week = dfl(w.w, 1); - // draw label - var point; - if (this.label) { - if (this.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.length / 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); - } - }; + 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); - /** - * Get the line width of the edge. Depends on width and whether one of the - * connected nodes is selected. - * @return {Number} width - * @private - */ - Edge.prototype._getLineWidth = function() { - if (this.selected == true) { - return Math.min(this.widthSelected, this.widthMax)*this.networkScaleInv; - } - else { - if (this.hover == true) { - return Math.min(this.hoverWidth, this.widthMax)*this.networkScaleInv; - } - else { - return this.width*this.networkScaleInv; + config._a[YEAR] = temp.year; + config._dayOfYear = temp.dayOfYear; } - } - }; - Edge.prototype._getViaCoordinates = function () { - var xVia = null; - var yVia = null; - var factor = this.smoothCurves.roundness; - var type = this.smoothCurves.type; + // 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; - 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; + if (config._d) { + return; } - else if (this.from.x > this.to.x) { - xVia = this.from.x - factor * dy; - yVia = this.from.y - factor * dy; + + currentDate = currentDateArray(config); + + //compute day of the year from weeks and weekdays + if (config._w && config._a[DATE] == null && config._a[MONTH] == null) { + dayOfYearFromWeekInfo(config); } - } - 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; + + //if the day of the year is set, figure out what it is + if (config._dayOfYear) { + yearToUse = dfl(config._a[YEAR], currentDate[YEAR]); + + if (config._dayOfYear > daysInYear(yearToUse)) { + config._pf._overflowDayOfYear = true; + } + + date = makeUTCDate(yearToUse, 0, config._dayOfYear); + config._a[MONTH] = date.getUTCMonth(); + config._a[DATE] = date.getUTCDate(); } - else if (this.from.x > this.to.x) { - xVia = this.from.x - factor * dy; - yVia = this.from.y + factor * dy; + + // 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]; } - } - 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; + + // 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]; } - else if (this.from.x > this.to.x) { - xVia = this.from.x - factor * dx; - yVia = this.from.y + factor * dx; + + 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); } - } - 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; + + 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); } - } - else if (type == 'horizontal') { - if (this.from.x < this.to.x) { - xVia = this.to.x - (1-factor) * dx; + + 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()]; + } } - else { - xVia = this.to.x + (1-factor) * dx; + + // date from string and format string + function makeDateFromStringAndFormat(config) { + + if (config._f === moment.ISO_8601) { + parseISO(config); + return; + } + + 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; + + tokens = expandFormat(config._f, lang).match(formattingTokens) || []; + + 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); + } + } + + // add remaining unparsed input length to the string + config._pf.charsLeftOver = stringLength - totalParsedInputLength; + if (string.length > 0) { + config._pf.unusedInput.push(string); + } + + // 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; + } + + dateFromConfig(config); + checkOverflow(config); } - 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; + + function unescapeFormat(s) { + return s.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) { + return p1 || p2 || p3 || p4; + }); } - else { - yVia = this.to.y + (1-factor) * dy; + + // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript + function regexpEscape(s) { + return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); } - } - 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; + + // date from string and array of format strings + function makeDateFromStringAndArray(config) { + var tempConfig, + bestMoment, + + scoreToBeat, + i, + currentScore; + + if (config._f.length === 0) { + config._pf.invalidFormat = true; + config._d = new Date(NaN); + return; } - 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; + + 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; + } + + // if there is any input that was not parsed add a penalty for that format + currentScore += tempConfig._pf.charsLeftOver; + + //or tokens + currentScore += tempConfig._pf.unusedTokens.length * 10; + + tempConfig._pf.score = currentScore; + + if (scoreToBeat == null || currentScore < scoreToBeat) { + scoreToBeat = currentScore; + bestMoment = tempConfig; + } } - } + + extend(config, bestMoment || tempConfig); } - 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; + + // date from iso format + function parseISO(config) { + var i, l, + string = config._i, + match = isoRegex.exec(string); + + 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; + } + } + + // date from iso format or fallback + function makeDateFromString(config) { + parseISO(config); + if (config._isValid === false) { + delete config._isValid; + moment.createFromInputFallback(config); + } + } + + function makeDateFromInput(config) { + var input = config._i, + matched = aspNetJsonRegex.exec(input); + + 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); + } + } + + 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); + + //the date constructor doesn't accept years < 1970 + if (y < 1970) { + date.setFullYear(y); + } + return date; + } + + function makeUTCDate(y) { + var date = new Date(Date.UTC.apply(null, arguments)); + if (y < 1970) { + date.setUTCFullYear(y); + } + return date; + } + + 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; + } + + /************************************ + Relative Time + ************************************/ + + + // 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); + } + + 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); + } + + + /************************************ + Week of Year + ************************************/ + + + // 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 (daysToDayOfWeek > end) { + daysToDayOfWeek -= 7; + } + + if (daysToDayOfWeek < end - 7) { + daysToDayOfWeek += 7; + } + + adjustedMoment = moment(mom).add('d', daysToDayOfWeek); + return { + week: Math.ceil(adjustedMoment.dayOfYear() / 7), + year: adjustedMoment.year() + }; + } + + //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; + + 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 + }; + } + + /************************************ + Top Level Functions + ************************************/ + + function makeMoment(config) { + var input = config._i, + format = config._f; + + if (input === null || (format === undefined && input === '')) { + return moment.invalid({nullInput: true}); + } + + if (typeof input === 'string') { + config._i = input = getLangDefinition().preparse(input); + } + + if (moment.isMoment(input)) { + config = cloneMoment(input); + + config._d = new Date(+input._d); + } else if (format) { + if (isArray(format)) { + makeDateFromStringAndArray(config); + } else { + makeDateFromStringAndFormat(config); + } + } else { + makeDateFromInput(config); + } + + return new Moment(config); + } + + moment = 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._i = input; + c._f = format; + c._l = lang; + c._strict = strict; + c._isUTC = false; + c._pf = defaultParsingFlags(); + + return makeMoment(c); + }; + + moment.suppressDeprecationWarnings = false; + + 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); + }); + + // 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; + } + + moment.min = function () { + var args = [].slice.call(arguments, 0); + + return pickBy('isBefore', args); + }; + + moment.max = function () { + var args = [].slice.call(arguments, 0); + + 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 makeMoment(c).utc(); + }; + + // creating with unix timestamp (in seconds) + moment.unix = function (input) { + return moment(input * 1000); + }; + + // duration + moment.duration = function (input, key) { + var duration = input, + // matching against regexp is expensive, do it on demand + match = null, + sign, + ret, + parseIso; + + 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]) + }; + } + + ret = new Duration(duration); + + if (moment.isDuration(input) && input.hasOwnProperty('_lang')) { + ret._lang = input._lang; + } + + return ret; + }; + + // version number + moment.version = VERSION; + + // default format + moment.defaultFormat = isoFormat; + + // constant that refers to the ISO standard + moment.ISO_8601 = function () {}; + + // Plugins that add properties should also add the key here (null value), + // so we can properly clone ourselves. + moment.momentProperties = momentProperties; + + // 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; + }; + + // 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')); + }; + + // for typechecking Duration objects + moment.isDuration = function (obj) { + return obj instanceof Duration; + }; + + for (i = lists.length - 1; i >= 0; --i) { + makeList(lists[i]); + } + + moment.normalizeUnits = function (units) { + return normalizeUnits(units); + }; + + moment.invalid = function (flags) { + var m = moment.utc(NaN); + if (flags != null) { + extend(m._pf, flags); + } + else { + m._pf.userInvalidated = true; + } + + return m; + }; + + moment.parseZone = function () { + return moment.apply(null, arguments).parseZone(); + }; + + moment.parseTwoDigitYear = function (input) { + return toInt(input) + (toInt(input) > 68 ? 1900 : 2000); + }; + + /************************************ + Moment Prototype + ************************************/ + + + extend(moment.fn = Moment.prototype, { + + clone : function () { + return moment(this); + }, + + valueOf : function () { + return +this._d + ((this._offset || 0) * 60000); + }, + + unix : function () { + return Math.floor(+this / 1000); + }, + + 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 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() + ]; + }, + + isValid : function () { + return isValid(this); + }, + + isDSTShifted : function () { + + if (this._a) { + return this.isValid() && compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()) > 0; + } + + return false; + }, + + parsingFlags : function () { + return extend({}, this._pf); + }, + + invalidAt: function () { + return this._pf.overflow; + }, + + utc : function () { + return this.zone(0); + }, + + local : function () { + this.zone(0); + this._isUTC = false; + return this; + }, + + format : function (inputString) { + var output = formatMoment(this, inputString || moment.defaultFormat); + return this.lang().postformat(output); + }, + + 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; + }, + + 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; + }, + + diff : function (input, units, asFloat) { + var that = makeAs(input, this), + zoneDiff = (this.zone() - that.zone()) * 6e4, + diff, output; + + units = normalizeUnits(units); + + 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); + }, + + from : function (time, withoutSuffix) { + return moment.duration(this.diff(time)).lang(this.lang()._abbr).humanize(!withoutSuffix); + }, + + fromNow : function (withoutSuffix) { + return this.from(moment(), withoutSuffix); + }, + + 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)); + }, + + isLeapYear : function () { + return isLeapYear(this.year()); + }, + + isDST : function () { + return (this.zone() < this.clone().month(0).zone() || + this.zone() < this.clone().month(5).zone()); + }, + + 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; + } + }, + + month : makeAccessor('Month', true), + + 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 */ + } + + // 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 this; + }, + + 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); + }, + + isBefore: function (input, units) { + units = typeof units !== 'undefined' ? units : 'millisecond'; + return +this.clone().startOf(units) < +moment(input).startOf(units); + }, + + 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; + } + ), + + 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; + } + ), + + // 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; + }, + + zoneAbbr : function () { + return this._isUTC ? "UTC" : ""; + }, + + zoneName : function () { + return this._isUTC ? "Coordinated Universal Time" : ""; + }, + + parseZone : function () { + if (this._tzm) { + this.zone(this._tzm); + } else if (typeof this._i === 'string') { + this.zone(this._i); + } + return this; + }, + + 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)); + }, + + quarter : function (input) { + return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3); + }, + + 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)); + }, + + week : function (input) { + var week = this.lang().week(this); + return input == null ? week : this.add("d", (input - week) * 7); + }, + + isoWeek : function (input) { + var week = weekOfYear(this, 1, 4).week; + return input == null ? week : this.add("d", (input - week) * 7); + }, + + weekday : function (input) { + var weekday = (this.day() + 7 - this.lang()._week.dow) % 7; + return input == null ? weekday : this.add("d", input - weekday); + }, + + 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); + }, + + isoWeeksInYear : function () { + return weeksInYear(this.year(), 1, 4); + }, + + weeksInYear : function () { + var weekInfo = this._lang._week; + return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy); + }, + + get : function (units) { + units = normalizeUnits(units); + return this[units](); + }, + + set : function (units, value) { + units = normalizeUnits(units); + if (typeof this[units] === 'function') { + this[units](value); + } + return this; + }, + + // 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; + } + } + }); + + function rawMonthSetter(mom, value) { + var dayOfMonth; + + // 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; + } + } + + dayOfMonth = Math.min(mom.date(), + daysInMonth(mom.year(), value)); + mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth); + return mom; + } + + function rawGetter(mom, unit) { + return mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit](); + } + + function rawSetter(mom, unit, value) { + if (unit === 'Month') { + return rawMonthSetter(mom, value); + } else { + return mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value); + } + } + + 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); + } + }; + } + + 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; + + // add aliased format methods + moment.fn.toJSON = moment.fn.toISOString; + + /************************************ + Duration Prototype + ************************************/ + + + extend(moment.duration.fn = Duration.prototype, { + + _bubble : function () { + var milliseconds = this._milliseconds, + days = this._days, + months = this._months, + data = this._data, + seconds, minutes, hours, years; + + // 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; + + hours = absRound(minutes / 60); + data.hours = hours % 24; + + days += absRound(hours / 24); + data.days = days % 30; + + months += absRound(days / 30); + data.months = months % 12; + + years = absRound(months / 12); + data.years = years; + }, + + weeks : function () { + return absRound(this.days() / 7); + }, + + valueOf : function () { + return this._milliseconds + + this._days * 864e5 + + (this._months % 12) * 2592e6 + + toInt(this._months / 12) * 31536e6; + }, + + humanize : function (withSuffix) { + var difference = +this, + output = relativeTime(difference, !withSuffix, this.lang()); + + if (withSuffix) { + output = this.lang().pastFuture(difference, output); + } + + return this.lang().postformat(output); + }, + + add : function (input, val) { + // supports only 2.0-style add(1, 's') or add(moment) + var dur = moment.duration(input, val); + + this._milliseconds += dur._milliseconds; + this._days += dur._days; + this._months += dur._months; + + this._bubble(); + + return this; + }, + + subtract : function (input, val) { + var dur = moment.duration(input, val); + + this._milliseconds -= dur._milliseconds; + this._days -= dur._days; + this._months -= dur._months; + + this._bubble(); + + return this; + }, + + get : function (units) { + units = normalizeUnits(units); + return this[units.toLowerCase() + 's'](); + }, + + as : function (units) { + units = normalizeUnits(units); + return this['as' + units.charAt(0).toUpperCase() + units.slice(1) + 's'](); + }, + + lang : moment.fn.lang, + + 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); + + 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' : ''); + } + }); + + function makeDurationGetter(name) { + moment.duration.fn[name] = function () { + return this._data[name]; + }; + } + + function makeDurationAsGetter(name, factor) { + moment.duration.fn['as' + name] = function () { + return +this / factor; + }; + } + + for (i in unitMillisecondFactors) { + if (unitMillisecondFactors.hasOwnProperty(i)) { + makeDurationAsGetter(i, unitMillisecondFactors[i]); + makeDurationGetter(i.toLowerCase()); + } + } + + makeDurationAsGetter('Weeks', 6048e5); + moment.duration.fn.asMonths = function () { + return (+this - this.years() * 31536e6) / 2592e6 + this.years() * 12; + }; + + + /************************************ + 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; + } + }); + + /* 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__(60)(module))) + +/***/ }, +/* 48 */ +/***/ 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'; + + /** + * @main + * @module hammer + * + * @class Hammer + * @static + */ + + /** + * 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', + + /** + * 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', + + /** + * Specifies whether zooming is enabled. Used by IE10> + * @property defaults.behavior.contentZooming + * @type {String} + * @default 'none' + */ + contentZooming: 'none', + + /** + * 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', + + /** + * 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)' + } + }; + + /** + * hammer document where the base events are added at + * @property DOCUMENT + * @type {HTMLElement} + * @default window.document + */ + Hammer.DOCUMENT = document; + + /** + * detect support for pointer events + * @property HAS_POINTEREVENTS + * @type {Boolean} + */ + Hammer.HAS_POINTEREVENTS = navigator.pointerEnabled || navigator.msPointerEnabled; + + /** + * detect support for touch events + * @property HAS_TOUCHEVENTS + * @type {Boolean} + */ + Hammer.HAS_TOUCHEVENTS = ('ontouchstart' in window); + + /** + * detect mobile browsers + * @property IS_MOBILE + * @type {Boolean} + */ + Hammer.IS_MOBILE = /mobile|tablet|ip(ad|hone|od)|android|silk/i.test(navigator.userAgent); + + /** + * 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; + + /** + * interval in which Hammer recalculates current velocity/direction/angle in ms + * @property CALCULATE_INTERVAL + * @type {Number} + * @default 25 + */ + Hammer.CALCULATE_INTERVAL = 25; + + /** + * 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'; + + /** + * 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'; + + /** + * if the window events are set... + * @property READY + * @writeOnce + * @type {Boolean} + * @default false + */ + Hammer.READY = false; + + /** + * plugins namespace + * @property plugins + * @type {Object} + */ + Hammer.plugins = Hammer.plugins || {}; + + /** + * gestures namespace + * see `/gestures` for the definitions + * @property gestures + * @type {Object} + */ + Hammer.gestures = Hammer.gestures || {}; + + /** + * setup events to detect gestures on the document + * this function is called when creating an new instance + * @private + */ + function setup() { + if(Hammer.READY) { + return; + } + + // find what eventtypes we add listeners to + Event.determineEventTypes(); + + // Register all gestures inside Hammer.gestures + Utils.each(Hammer.gestures, function(gesture) { + Detection.register(gesture); + }); + + // Add touch events on the document + Event.onTouch(Hammer.DOCUMENT, EVENT_MOVE, Detection.detect); + Event.onTouch(Hammer.DOCUMENT, EVENT_END, Detection.detect); + + // Hammer is ready...! + Hammer.READY = true; + } + + /** + * @module hammer + * + * @class Utils + * @static + */ + 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; + }, + + /** + * 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); + }, + + /** + * 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; + + // 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; + } + } + } + }, + + /** + * 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; + } + }, + + /** + * 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; + }, + + /** + * 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 + }; + } + + Utils.each(touches, function(touch) { + pageX.push(touch.pageX); + pageY.push(touch.pageY); + clientX.push(touch.clientX); + clientY.push(touch.clientY); + }); + + 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 + }; + }, + + /** + * 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; + + return Math.atan2(y, x) * 180 / Math.PI; + }, + + /** + * 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); + + if(x >= y) { + return touch1.clientX - touch2.clientX > 0 ? DIRECTION_LEFT : DIRECTION_RIGHT; + } + return touch1.clientY - touch2.clientY > 0 ? DIRECTION_UP : DIRECTION_DOWN; + }, + + /** + * 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)); + }, + + /** + * 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; + }, + + /** + * 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; + }, + + /** + * 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; + }, + + /** + * 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); + + 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; + } + } + }, + + /** + * 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; + } + + // set the css properties + Utils.each(props, function(value, prop) { + Utils.setPrefixedCss(element, prop, value, toggle); + }); + + 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(); + }); + } + }; + + + /** + * @module hammer + */ + /** + * @class Event + * @static + */ + 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, + + /** + * if EVENT_START has been fired + * @property started + * @private + * @type {Boolean} + */ + started: false, + + /** + * 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); + }); + }, + + /** + * 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); + }); + }, + + /** + * 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; + + var onTouchHandler = function onTouchHandler(ev) { + var srcType = ev.type.toLowerCase(), + isPointer = Hammer.HAS_POINTEREVENTS, + isMouse = Utils.inStr(srcType, 'mouse'), + triggerType; + + // 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; + + // 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; + } + + // update the pointer event before entering the detection + if(isPointer && eventType != EVENT_END) { + PointerEvent.updatePointer(eventType, ev); + } + + // we are in a touch/down state, so allowed detection of gestures + if(self.shouldDetect) { + triggerType = self.doDetect.call(self, ev, eventType, element, handler); + } + + // ...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(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; + + // 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; + + // keep track of how many touches have been removed + changedLength = touchList.length - ((ev.changedTouches) ? ev.changedTouches.length : 1); } - 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; + + // 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; } - } - 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; + + // detection has been started, we keep track of this, see above + this.started = true; + + // generate some event data, some basic information + var evData = this.collectEventData(element, triggerType, touchList, ev); + + // 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); } - 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; + + // 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); + + evData.eventType = triggerType; + delete evData.changedLength; } - } - } - } + // trigger the END event + if(triggerType == EVENT_END) { + handler.call(Detection, evData); - return {x:xVia, y:yVia}; - } + // ...and we are done with the detection + // so reset everything to start each detection totally fresh + this.started = false; + } - /** - * Draw a line between two nodes - * @param {CanvasRenderingContext2D} ctx - * @private - */ - Edge.prototype._line = function (ctx) { - // draw a straight line - ctx.beginPath(); - ctx.moveTo(this.from.x, this.from.y); - if (this.smoothCurves.enabled == true) { - if (this.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 { - ctx.lineTo(this.to.x, this.to.y); - ctx.stroke(); - return null; - } - }; + return triggerType; + }, - /** - * 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(); - }; + /** + * 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' + ]; + } - /** - * 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.fontSize + "px " + this.fontFace; - ctx.fillStyle = this.fontFill; - var width = ctx.measureText(text).width; - var height = this.fontSize; - var left = x - width / 2; - var top = y - height / 2; + EVENT_TYPES[EVENT_START] = types[0]; + EVENT_TYPES[EVENT_MOVE] = types[1]; + EVENT_TYPES[EVENT_END] = types[2]; + return EVENT_TYPES; + }, - ctx.fillRect(left, top, width, height); + /** + * 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(); + } - // draw text - ctx.fillStyle = this.fontColor || "black"; - ctx.textAlign = "left"; - ctx.textBaseline = "top"; - ctx.fillText(text, left, top); - } - }; + // get the touchlist + if(ev.touches) { + if(eventType == EVENT_MOVE) { + return ev.touches; + } - /** - * 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.color.highlight;} - else if (this.hover == true) {ctx.strokeStyle = this.color.hover;} - else {ctx.strokeStyle = this.color.color;} + var identifiers = []; + var concat = [].concat(Utils.toArray(ev.touches), Utils.toArray(ev.changedTouches)); + var touchList = []; - ctx.lineWidth = this._getLineWidth(); + Utils.each(concat, function(touch) { + if(Utils.inArray(identifiers, touch.identifier) === false) { + touchList.push(touch); + } + identifiers.push(touch.identifier); + }); - 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.dash.length !== undefined && this.dash.gap !== undefined) { - pattern = [this.dash.length,this.dash.gap]; - } - else { - pattern = [5,5]; - } + return touchList; + } - // set dash settings for chrome or firefox - if (typeof ctx.setLineDash !== 'undefined') { //Chrome - ctx.setLineDash(pattern); - ctx.lineDashOffset = 0; + // make fake touchList from mouse position + ev.identifier = 1; + return [ev]; + }, - } else { //Firefox - ctx.mozDash = pattern; - ctx.mozDashOffset = 0; - } + /** + * 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; + } - // draw the line - via = this._line(ctx); + return { + center: Utils.getCenter(touches), + timeStamp: Date.now(), + target: ev.target, + touches: touches, + eventType: eventType, + pointerType: pointerType, + srcEvent: ev, - // restore the dash settings. - if (typeof ctx.setLineDash !== 'undefined') { //Chrome - ctx.setLineDash([0]); - ctx.lineDashOffset = 0; + /** + * 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(); + }, - } else { //Firefox - ctx.mozDash = [0]; - ctx.mozDashOffset = 0; - } - } - else { // unsupporting smooth lines - // draw dashed line - ctx.beginPath(); - ctx.lineCap = 'round'; - if (this.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.dash.length,this.dash.gap,this.dash.altLength,this.dash.gap]); - } - else if (this.dash.length !== undefined && this.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.dash.length,this.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(); - } + /** + * stop bubbling the event up to its parents + */ + stopPropagation: function() { + this.srcEvent.stopPropagation(); + }, - // draw label - if (this.label) { - var point; - if (this.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); + /** + * immediately stop gesture detection + * might be useful after a swipe was detected + * @return {*} + */ + stopDetect: function() { + return Detection.stopDetect(); + } + }; } - this._label(ctx, this.label, point.x, point.y); - } }; - /** - * 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 - } - }; /** - * 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 + * @module hammer + * + * @class PointerEvent + * @static */ - 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) - } - }; + var PointerEvent = Hammer.PointerEvent = { + /** + * holds all pointers, by `identifier` + * @property pointers + * @type {Object} + */ + pointers: {}, - /** - * 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.color.highlight; ctx.fillStyle = this.color.highlight;} - else if (this.hover == true) {ctx.strokeStyle = this.color.hover; ctx.fillStyle = this.color.hover;} - else {ctx.strokeStyle = this.color.color; ctx.fillStyle = this.color.color;} - ctx.lineWidth = this._getLineWidth(); + /** + * 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; + }, - if (this.from != this.to) { - // draw line - var via = this._line(ctx); + /** + * 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 angle = Math.atan2((this.to.y - this.from.y), (this.to.x - this.from.x)); - var length = (10 + 5 * this.width) * this.arrowScaleFactor; - // draw an arrow halfway the line - if (this.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); - } + /** + * 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.arrow(point.x, point.y, angle, length); - ctx.fill(); - ctx.stroke(); + var pt = ev.pointerType, + types = {}; - // 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.length); - 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; + 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]; + }, + + /** + * reset the stored pointers + * @method reset + */ + reset: function resetList() { + this.pointers = {}; } - this._circle(ctx, x, y, radius); + }; - // draw all arrows - var angle = 0.2 * Math.PI; - var length = (10 + 5 * this.width) * this.arrowScaleFactor; - point = this._pointOnCircle(x, y, radius, 0.5); - ctx.arrow(point.x, point.y, angle, length); - ctx.fill(); - ctx.stroke(); - // draw label - if (this.label) { - point = this._pointOnCircle(x, y, radius, 0.5); - this._label(ctx, this.label, point.x, point.y); - } - } - }; + /** + * @module hammer + * + * @class Detection + * @static + */ + var Detection = Hammer.detection = { + // contains all registred Hammer.gestures in the correct order + gestures: [], + + // 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, + // when this becomes true, no gestures are fired + stopped: false, - /** - * 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.color.highlight; ctx.fillStyle = this.color.highlight;} - else if (this.hover == true) {ctx.strokeStyle = this.color.hover; ctx.fillStyle = this.color.hover;} - else {ctx.strokeStyle = this.color.color; ctx.fillStyle = this.color.color;} + /** + * 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; + } - ctx.lineWidth = this._getLineWidth(); + this.stopped = 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); + // 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 + }; - 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; + this.detect(eventData); + }, - var via; - if (this.smoothCurves.dynamic == true && this.smoothCurves.enabled == true ) { - via = this.via; - } - else if (this.smoothCurves.enabled == true) { - via = this._getViaCoordinates(); - } + /** + * Hammer.gesture detection + * @method detect + * @param {Object} eventData + * @return {any} + */ + detect: function detect(eventData) { + if(!this.current || this.stopped) { + return; + } - if (this.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; + // extend event data with calculations about scale, distance etc + eventData = this.extendEventData(eventData); - var xTo,yTo; - if (this.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; - } + // hammer instance and instance options + var inst = this.current.inst, + instOptions = inst.options; - ctx.beginPath(); - ctx.moveTo(xFrom,yFrom); - if (this.smoothCurves.enabled == true && via.x != null) { - ctx.quadraticCurveTo(via.x,via.y,xTo, yTo); - } - else { - ctx.lineTo(xTo, yTo); - } - ctx.stroke(); + // 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); - // draw arrow at the end of the line - length = (10 + 5 * this.width) * this.arrowScaleFactor; - ctx.arrow(xTo, yTo, angle, length); - ctx.fill(); - ctx.stroke(); + // store as previous event event + if(this.current) { + this.current.lastEvent = eventData; + } - // draw label - if (this.label) { - var point; - if (this.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 { - // draw circle - var node = this.from; - var x, y, arrow; - var radius = 0.25 * Math.max(100,this.length); - 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(eventData.eventType == EVENT_END) { + this.stopDetect(); + } - // draw all arrows - var length = (10 + 5 * this.width) * this.arrowScaleFactor; - ctx.arrow(arrow.x, arrow.y, arrow.angle, length); - ctx.fill(); - ctx.stroke(); + return eventData; + }, - // draw label - if (this.label) { - point = this._pointOnCircle(x, y, radius, 0.5); - this._label(ctx, this.label, point.x, point.y); - } - } - }; + /** + * 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; - /** - * 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.smoothCurves.enabled == true) { - var xVia, yVia; - if (this.smoothCurves.enabled == true && this.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; + 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; } - lastX = x; lastY = y; - } - return minDistance - } - else { - return this._getDistanceToLine(x1,y1,x2,y2,x3,y3); - } - } - else { - var x, y, dx, dy; - var radius = this.length / 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; + if(ev.eventType == EVENT_TOUCH || ev.eventType == EVENT_RELEASE) { + cur.futureCalcEvent = ev; + } - if (u > 1) { - u = 1; - } - else if (u < 0) { - u = 0; - } + 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); - var x = x1 + u * px, - y = y1 + u * py, - dx = x - x3, - dy = y - y3; + cur.lastCalcEvent = cur.futureCalcEvent || ev; + cur.futureCalcEvent = ev; + } - //# 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 + ev.velocityX = calcData.velocity.x; + ev.velocityY = calcData.velocity.y; + ev.interimAngle = calcData.angle; + ev.interimDirection = calcData.direction; + }, - return Math.sqrt(dx*dx + dy*dy); - } + /** + * 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 allows the zoom level of the network to influence the rendering - * - * @param scale - */ - Edge.prototype.setScale = function(scale) { - this.networkScaleInv = 1.0/scale; - }; + // 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 + }); + }); + } + var deltaTime = ev.timeStamp - startEv.timeStamp, + deltaX = ev.center.clientX - startEv.center.clientX, + deltaY = ev.center.clientY - startEv.center.clientY; - Edge.prototype.select = function() { - this.selected = true; - }; + this.getCalculatedData(ev, lastEv.center, deltaTime, deltaX, deltaY); - Edge.prototype.unselect = function() { - this.selected = false; - }; + Utils.extend(ev, { + startEvent: startEv, - Edge.prototype.positionBezierNode = function() { - if (this.via !== null) { - this.via.x = 0.5 * (this.from.x + this.to.x); - this.via.y = 0.5 * (this.from.y + this.to.y); - } - }; + deltaTime: deltaTime, + deltaX: deltaX, + deltaY: deltaY, - /** - * 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); - } + 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) + }); - 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; - } + return ev; + }, - this.controlNodes.from.draw(ctx); - this.controlNodes.to.draw(ctx); - } - else { - this.controlNodes = {from:null, to:null, positions:{}}; - } - }; + /** + * 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; + } - /** - * Enable control nodes. - * @private - */ - Edge.prototype._enableControlNodes = function() { - this.controlNodesEnabled = true; + // extend Hammer default options with the Hammer.gesture options + Utils.extend(Hammer.defaults, options, true); + + // set its index + gesture.index = gesture.index || 1000; + + // add Hammer.gesture to the list + this.gestures.push(gesture); + + // 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; + }); + + return this.gestures; + } }; + /** - * disable control nodes - * @private + * @module hammer */ - Edge.prototype._disableControlNodes = function() { - this.controlNodesEnabled = false; - }; /** - * 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 + * 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} */ - 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)); + Hammer.Instance = function(element, options) { + var self = this; + + // setup HammerJS window events and register all gestures + // this also sets up the default options + setup(); + + /** + * @property element + * @type {HTMLElement} + */ + this.element = element; + + /** + * @property enabled + * @type {Boolean} + * @protected + */ + this.enabled = true; + + /** + * 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; + }); + + this.options = Utils.extend(Utils.extend({}, Hammer.defaults), options || {}); - 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; - } - }; + // 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); + } + /** + * 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); + } + }); - /** - * 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(); - } + /** + * keep a list of user event handlers which needs to be removed when calling 'dispose' + * @property eventHandlers + * @type {Array} + */ + this.eventHandlers = []; }; - /** - * 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; + 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; + }, - var via; - if (this.smoothCurves.dynamic == true && this.smoothCurves.enabled == true) { - via = this.via; - } - else if (this.smoothCurves.enabled == true) { - via = this._getViaCoordinates(); - } + /** + * unbind events to the instance + * @method off + * @chainable + * @param {String} gestures + * @param {Function} handler + */ + off: function offEvent(gestures, handler) { + var self = this; - if (this.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; + 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; + }, - var xTo,yTo; - if (this.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; - } + /** + * trigger gesture event + * @method trigger + * @chainable + * @param {String} gesture + * @param {Object} [eventData] + */ + trigger: function triggerEvent(gesture, eventData) { + // optional + if(!eventData) { + eventData = {}; + } - return {from:{x:xFrom,y:yFrom},to:{x:xTo,y:yTo}}; - }; + // create DOM event + var event = Hammer.DOCUMENT.createEvent('Event'); + event.initEvent(gesture, true, true); + event.gesture = eventData; - module.exports = Edge; + // 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; + } -/***/ }, -/* 49 */ -/***/ function(module, exports, __webpack_require__) { + element.dispatchEvent(event); + return this; + }, - /** - * 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; - } + /** + * enable of disable hammer.js detection + * @method enable + * @chainable + * @param {Boolean} state + */ + enable: function enable(state) { + this.enabled = state; + return this; + }, - // 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' + /** + * 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); } - } - } - } - this.x = 0; - this.y = 0; - this.padding = 5; + this.eventHandlers = []; - if (x !== undefined && y !== undefined ) { - this.setPosition(x, y); - } - if (text !== undefined) { - this.setText(text); - } + // unbind the start event listener + Event.off(this.element, EVENT_TYPES[EVENT_START], this.eventStartHandler); - // 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); - } + return null; + } + }; + + /** + * @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 + */ /** - * @param {number} x Horizontal position of the popup window - * @param {number} y Vertical position of the popup window + * @event drag + * @param {Object} ev */ - Popup.prototype.setPosition = function(x, y) { - this.x = parseInt(x); - this.y = parseInt(y); - }; - /** - * Set the text for the popup window. This can be HTML code - * @param {string} text + * @event dragstart + * @param {Object} ev + */ + /** + * @event dragend + * @param {Object} ev + */ + /** + * @event drapleft + * @param {Object} ev + */ + /** + * @event dragright + * @param {Object} ev + */ + /** + * @event dragup + * @param {Object} ev + */ + /** + * @event dragdown + * @param {Object} ev */ - Popup.prototype.setText = function(text) { - this.frame.innerHTML = text; - }; /** - * Show the popup window - * @param {boolean} show Optional. Show or hide the window + * @param {String} name */ - Popup.prototype.show = function (show) { - if (show === undefined) { - show = true; - } + (function(name) { + var triggered = false; - if (show) { - var height = this.frame.clientHeight; - var width = this.frame.clientWidth; - var maxHeight = this.frame.parentNode.clientHeight; - var maxWidth = this.frame.parentNode.clientWidth; + function dragGesture(ev, inst) { + var cur = Detection.current; - var top = (this.y - height); - if (top + height + this.padding > maxHeight) { - top = maxHeight - height - this.padding; - } - if (top < this.padding) { - top = this.padding; - } + // max touches + if(inst.options.dragMaxTouches > 0 && + ev.touches.length > inst.options.dragMaxTouches) { + return; + } - var left = this.x; - if (left + width + this.padding > maxWidth) { - left = maxWidth - width - this.padding; - } - if (left < this.padding) { - left = this.padding; - } + switch(ev.eventType) { + case EVENT_START: + triggered = false; + break; - this.frame.style.left = left + "px"; - this.frame.style.top = top + "px"; - this.frame.style.visibility = "visible"; - } - else { - this.hide(); - } - }; + 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; + } - /** - * Hide the popup window - */ - Popup.prototype.hide = function () { - this.frame.style.visibility = "hidden"; - }; + var startCenter = cur.startEvent.center; - module.exports = Popup; + // 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; + // recalculate event data using new start point + ev = Detection.extendEventData(ev); + } + } -/***/ }, -/* 50 */ -/***/ function(module, exports, __webpack_require__) { + // lock drag to axis? + if(cur.lastEvent.dragLockToAxis || + ( inst.options.dragLockToAxis && + inst.options.dragLockMinDistance <= ev.distance + )) { + ev.dragLockToAxis = true; + } - 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); + // 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; + } + } - /** - * 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]; + // first time, trigger dragstart event + if(!triggered) { + inst.trigger(name + 'start', ev); + triggered = true; + } + + // trigger events + inst.trigger(name, ev); + inst.trigger(name + ev.direction, ev); + + var isVertical = Utils.isVertical(ev.direction); + + // block the browser events + if((inst.options.dragBlockVertical && isVertical) || + (inst.options.dragBlockHorizontal && !isVertical)) { + ev.preventDefault(); + } + break; + + case EVENT_RELEASE: + if(triggered && ev.changedLength <= inst.options.dragMaxTouches) { + inst.trigger(name + 'end', ev); + triggered = false; + } + break; + + case EVENT_END: + triggered = false; + break; + } } - } - }; + 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 + } + }; + })('drag'); /** - * removes a mixin from the network object. + * @module gestures + */ + /** + * trigger a simple gesture event, so you can do anything in your handler. + * only usable if you know what your doing... * - * @param {Object} sourceVariable | this object has to contain functions. - * @private + * @class Gesture + * @static */ - exports._clearMixin = function (sourceVariable) { - for (var mixinFunction in sourceVariable) { - if (sourceVariable.hasOwnProperty(mixinFunction)) { - this[mixinFunction] = undefined; - } - } - }; - - /** - * Mixin the physics system and initialize the parameters required. - * - * @private + * @event gesture + * @param {Object} ev */ - exports._loadPhysicsSystem = function () { - this._loadMixin(PhysicsMixin); - this._loadSelectedForceSolver(); - if (this.constants.configurePhysics == true) { - this._loadPhysicsConfiguration(); - } + Hammer.gestures.Gesture = { + name: 'gesture', + index: 1337, + handler: function releaseGesture(ev, inst) { + inst.trigger(this.name, ev); + } }; - /** - * Mixin the cluster system and initialize the parameters required. - * - * @private + * @module gestures */ - exports._loadClusterSystem = function () { - this.clusterSession = 0; - this.hubThreshold = 5; - this._loadMixin(ClusterMixin); - }; - - /** - * Mixin the sector system and initialize the parameters required + * Touch stays at the same place for x time * - * @private + * @class Hold + * @static */ - 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._loadMixin(SectorsMixin); - }; - - /** - * Mixin the selection system and initialize the parameters required - * - * @private + * @event hold + * @param {Object} ev */ - exports._loadSelectionSystem = function () { - this.selectionObj = {nodes: {}, edges: {}}; - - this._loadMixin(SelectionMixin); - }; - /** - * Mixin the navigationUI (User Interface) system and initialize the parameters required - * - * @private + * @param {String} name */ - exports._loadManipulationSystem = function () { - // reset global variables -- these are used by the selection of nodes and edges. - this.blockConnectingEdgeSelection = false; - this.forceAppendSelection = false; + (function(name) { + var timer; - 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); - } + function holdGesture(ev, inst) { + var options = inst.options, + current = Detection.current; - 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); - } + switch(ev.eventType) { + case EVENT_START: + clearTimeout(timer); - 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); - } + // set the gesture so we can check in the timeout if it still is + current.name = name; - // load the manipulation functions - this._loadMixin(ManipulationMixin); + // 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; - // 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); + case EVENT_MOVE: + if(ev.distance > options.holdThreshold) { + clearTimeout(timer); + } + break; - this.manipulationDiv = undefined; - this.editModeDiv = undefined; - this.closeDiv = undefined; - // remove the mixin functions - this._clearMixin(ManipulationMixin); + 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'); /** - * Mixin the navigation (User Interface) system and initialize the parameters required + * @module gestures + */ + /** + * when a touch is being released from the page * - * @private + * @class Release + * @static */ - 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(); - } + /** + * @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); + } + } }; - /** - * Mixin the hierarchical layout system. + * @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(); + * }); + * ```` * - * @private + * @class Swipe + * @static + */ + /** + * @event swipe + * @param {Object} ev + */ + /** + * @event swipeleft + * @param {Object} ev */ - exports._loadHierarchySystem = function () { - this._loadMixin(HierarchicalLayoutMixin); - }; - - -/***/ }, -/* 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 + * @event swiperight + * @param {Object} ev */ - exports._toggleBarnesHut = function () { - this.constants.physics.barnesHut.enabled = !this.constants.physics.barnesHut.enabled; - this._loadSelectedForceSolver(); - this.moving = true; - this.start(); - }; - - /** - * This loads the node force solver based on the barnes hut or repulsion algorithm - * - * @private + * @event swipeup + * @param {Object} ev */ - exports._loadSelectedForceSolver = function () { - // this overloads the this._calculateNodeForces - if (this.constants.physics.barnesHut.enabled == true) { - this._clearMixin(RepulsionMixin); - this._clearMixin(HierarchialRepulsionMixin); + /** + * @event swipedown + * @param {Object} ev + */ + Hammer.gestures.Swipe = { + name: 'swipe', + index: 40, + defaults: { + /** + * @property swipeMinTouches + * @type {Number} + * @default 1 + */ + swipeMinTouches: 1, - 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; + /** + * @property swipeMaxTouches + * @type {Number} + * @default 1 + */ + swipeMaxTouches: 1, - this._loadMixin(BarnesHutMixin); - } - else if (this.constants.physics.hierarchicalRepulsion.enabled == true) { - this._clearMixin(BarnesHutMixin); - this._clearMixin(RepulsionMixin); + /** + * horizontal swipe velocity + * @property swipeVelocityX + * @type {Number} + * @default 0.6 + */ + swipeVelocityX: 0.6, - 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; + /** + * vertical swipe velocity + * @property swipeVelocityY + * @type {Number} + * @default 0.6 + */ + swipeVelocityY: 0.6 + }, - this._loadMixin(HierarchialRepulsionMixin); - } - else { - this._clearMixin(BarnesHutMixin); - this._clearMixin(HierarchialRepulsionMixin); - this.barnesHutTree = undefined; + handler: function swipeGesture(ev, inst) { + if(ev.eventType == EVENT_RELEASE) { + var touches = ev.touches.length, + options = inst.options; - 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; + // max touches + if(touches < options.swipeMinTouches || + touches > options.swipeMaxTouches) { + return; + } - this._loadMixin(RepulsionMixin); - } + // 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); + } + } + } }; /** - * 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. + * @module gestures + */ + /** + * Single tap and a double tap on a place * - * @private + * @class Tap + * @static + */ + /** + * @event tap + * @param {Object} ev + */ + /** + * @event doubletap + * @param {Object} ev */ - 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(); - } - }; - /** - * Calculate the external forces acting on the nodes - * Forces are caused by: edges, repulsing forces between nodes, gravity - * @private + * @param {String} name */ - 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 + (function(name) { + var hasMoved = false; - this._calculateGravitationalForces(); - this._calculateNodeForces(); + function tapGesture(ev, inst) { + var options = inst.options, + current = Detection.current, + prev = Detection.previous, + sincePrev, + didDoubleTap; - 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(); - } - } - } - }; + switch(ev.eventType) { + case EVENT_START: + hasMoved = false; + break; + case EVENT_MOVE: + hasMoved = hasMoved || (ev.distance > options.tapMaxDistance); + break; - /** - * 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._updateCalculationNodes = function () { - if (this.constants.smoothCurves.enabled == true && this.constants.smoothCurves.dynamic == true) { - this.calculationNodes = {}; - this.calculationNodeIndices = []; + 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; - 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); + // 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; } - } } - for (var idx in this.calculationNodes) { - if (this.calculationNodes.hasOwnProperty(idx)) { - this.calculationNodeIndices.push(idx); - } - } - } - else { - this.calculationNodes = this.nodes; - this.calculationNodeIndices = this.nodeIndices; - } - }; + 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, + + /** + * 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'); /** - * this function applies the central gravity effect to keep groups from floating off + * @module gestures + */ + /** + * when a touch is being touched at the page * - * @private + * @class Touch + * @static */ - exports._calculateGravitationalForces = function () { - var dx, dy, distance, node, i; - var nodes = this.calculationNodes; - var gravity = this.constants.physics.centralGravity; - var gravityForce = 0; + /** + * @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, - 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); + /** + * 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; + } - gravityForce = (distance == 0) ? 0 : (gravity / distance); - node.fx = dx * gravityForce; - node.fy = dy * gravityForce; - } - else { - node.fx = 0; - node.fy = 0; + if(inst.options.preventDefault) { + ev.preventDefault(); + } + + if(ev.eventType == EVENT_TOUCH) { + inst.trigger('touch', ev); + } } - } }; - - - /** - * this function calculates the effects of the springs in the case of unsmooth curves. + * @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. * - * @private + * @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 */ - 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.customLength ? edge.length : this.constants.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; + /** + * @param {String} name + */ + (function(name) { + var triggered = false; - fx = dx * springForce; - fy = dy * springForce; + function transformGesture(ev, inst) { + switch(ev.eventType) { + case EVENT_START: + triggered = false; + break; - edge.from.fx += fx; - edge.from.fy += fy; - edge.to.fx -= fx; - edge.to.fy -= fy; - } - } - } - } - }; + 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); + // 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; + } + // we are transforming! + Detection.current.name = name; - /** - * This function calculates the springforces on the nodes, accounting for the support nodes. - * - * @private - */ - exports._calculateSpringForcesWithSupport = function () { - var edgeLength, edge, edgeId, combinedClusterSize; - var edges = this.edges; + // first time, trigger dragstart event + if(!triggered) { + inst.trigger(name + 'start', ev); + triggered = true; + } - // 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; + inst.trigger(name, ev); // basic transform event - edgeLength = edge.customLength ? edge.length : this.constants.physics.springLength; + // trigger rotate event + if(rotationThreshold > inst.options.transformMinRotation) { + inst.trigger('rotate', ev); + } - combinedClusterSize = node1.clusterSize + node3.clusterSize - 2; + // trigger pinch event + if(scaleThreshold > inst.options.transformMinScale) { + inst.trigger('pinch', ev); + inst.trigger('pinch' + (ev.scale < 1 ? 'in' : 'out'), ev); + } + break; - // 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); - } + case EVENT_RELEASE: + if(triggered && ev.changedLength < 2) { + inst.trigger(name + 'end', ev); + triggered = false; + } + break; } - } } - } - }; + 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'); /** - * 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 + * @module hammer */ - 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; + // 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; + } - node1.fx += fx; - node1.fy += fy; - node2.fx -= fx; - node2.fy -= fy; - }; + })(window); +/***/ }, +/* 49 */ +/***/ function(module, exports, __webpack_require__) { /** - * Load the HTML for the physics config and bind it - * @private + * Creation of the ClusterMixin var. + * + * This contains all the functions the Network object can use to employ clustering */ - exports._loadPhysicsConfiguration = function () { - if (this.physicsConfiguration === undefined) { - this.backupConstants = {}; - util.deepExtend(this.backupConstants,this.constants); - 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 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); - 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"); + // updates the lables after clustering + this.updateLabels(); - 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"); + // 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(); + }; - 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"); + /** + * This function clusters until the initialMaxNodes has been reached + * + * @param {Number} maxNumberOfNodes + * @param {Boolean} reposition + */ + exports.clusterToFit = function(maxNumberOfNodes, reposition) { + var numberOfNodes = this.nodeIndices.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; + 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(); } - if (this.constants.hierarchicalLayout.enabled) { - radioButton3.checked = true; + else { + this.increaseClusterLevel(); // this also includes a cluster normalization } - var graph_toggleSmooth = document.getElementById("graph_toggleSmooth"); - var graph_repositionNodes = document.getElementById("graph_repositionNodes"); - var graph_generateOptions = document.getElementById("graph_generateOptions"); + numberOfNodes = this.nodeIndices.length; + level += 1; + } - 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"; + // after the clustering we reposition the nodes to reduce the initial chaos + if (level > 0 && reposition == true) { + this.repositionNodes(); + } + this._updateCalculationNodes(); + }; + + /** + * This function can be called to open up a specific cluster. It is only called by + * It will unpack the cluster back one level. + * + * @param node | Node object: cluster to open. + */ + 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; + + // we decluster until we reach a decent number of nodes + while ((this.nodeIndices.length < this.constants.clustering.initialMaxNodes) && (level < 10)) { + this.decreaseClusterLevel(); + level += 1; } + } + else { + this._expandClusterNode(node,false,true); - switchConfigurations.apply(this); + // update the index list, dynamic edges and labels + this._updateNodeIndexList(); + this._updateDynamicEdges(); + this._updateCalculationNodes(); + this.updateLabels(); + } - radioButton1.onchange = switchConfigurations.bind(this); - radioButton2.onchange = switchConfigurations.bind(this); - radioButton3.onchange = switchConfigurations.bind(this); + // if the simulation was settled, we restart the simulation if a cluster has been formed or expanded + if (this.moving != isMovingBeforeClustering) { + this.start(); } }; + /** - * This overwrites the this.constants. - * - * @param constantsVariableName - * @param value - * @private + * This calls the updateClustes with default arguments */ - 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.updateClustersDefault = function() { + if (this.constants.clustering.enabled == true) { + this.updateClusters(0,false,false); } }; /** - * this function is bound to the toggle smooth curves button. That is also why it is not in the prototype. + * 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. */ - 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.increaseClusterLevel = function() { + this.updateClusters(-1,false,true); + }; - this._configureSmoothCurves(false); - } /** - * this function is used to scramble the nodes - * + * 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. */ - 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.repositionNodes(); - } - this.moving = true; - this.start(); - } + exports.decreaseClusterLevel = function() { + this.updateClusters(1,false,true); + }; + /** - * this is used to generate an options file from the playing with physics system. + * 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 + * */ - 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.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(); } - 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 += '};' + + // 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 { - 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 += ", " - } - } - options += '}' + 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 { - options += "enabled:true}"; + // if a cluster takes up a set percentage of the active window + this._openClustersBySize(); } - options += '};' } + 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(); + } - this.optionsDiv.innerHTML = options; - } - - /** - * this is used to switch between barnesHut, repulsion and hierarchical. - * - */ - 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"; - } + // we now reduce chains. + if (this.previousScale > this.scale || zoomDirection == -1) { // zoom out + this.handleChains(); + this._updateNodeIndexList(); } - this._restoreNodes(); - if (radioButton == "R") { - this.constants.hierarchicalLayout.enabled = false; - this.constants.physics.hierarchicalRepulsion.enabled = false; - this.constants.physics.barnesHut.enabled = false; + + this.previousScale = this.scale; + + // 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(); } - 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(); + + 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 { - 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._updateCalculationNodes(); + }; /** - * this generates the ranges depending on the iniital values. - * - * @param id - * @param map - * @param constantsVariableName + * This function handles the chains. It is called on every updateClusters(). */ - 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 { - document.getElementById(valueId).value = parseInt(map) * parseFloat(rangeValue); - this._overWriteGraphConstants(constantsVariableName, parseInt(map) * parseFloat(rangeValue)); - } + 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 (constantsVariableName == "hierarchicalLayout_direction" || - constantsVariableName == "hierarchicalLayout_levelSeparation" || - constantsVariableName == "hierarchicalLayout_nodeSpacing") { - this._setupHierarchicalLayout(); } - this.moving = true; - this.start(); - } - - -/***/ }, -/* 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 functions starts clustering by hubs + * The minimum hub threshold is set globally * * @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._aggregateHubs = function(force) { + this._getHubSize(); + this._formClustersByHub(force,false); + }; - // 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; + /** + * This function is fired by keypress. It forces hubs to form. + * + */ + exports.forceAggregateHubs = function(doNotStart) { + var isMovingBeforeClustering = this.moving; + var amountOfNodes = this.nodeIndices.length; - dx = node2.x - node1.x; - dy = node2.y - node1.y; - distance = Math.sqrt(dx * dx + dy * dy); + this._aggregateHubs(true); - 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)) - } + // update the index list, dynamic edges and labels + this._updateNodeIndexList(); + this._updateDynamicEdges(); + this.updateLabels(); - // amplify the repulsion for clusters. - repulsingForce *= (combinedClusterSize == 0) ? 1 : 1 + combinedClusterSize * this.constants.clustering.forceAmplification; - repulsingForce = repulsingForce / distance; + // if a cluster was formed, we increase the clusterSession + if (this.nodeIndices.length != amountOfNodes) { + this.clusterSession += 1; + } - fx = dx * repulsingForce; - fy = dy * repulsingForce; + 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(); + } + } + }; - node1.fx -= fx; - node1.fy -= fy; - node2.fx += fx; - node2.fy += fy; + /** + * If a cluster takes up more than a set percentage of the screen, open the cluster + * + * @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); + } } } } }; -/***/ }, -/* 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 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._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) { + 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(); + } + }; - dx = node2.x - node1.x; - dy = node2.y - node1.y; - distance = Math.sqrt(dx * dx + dy * dy); + /** + * 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; + // 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]; - 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; + // 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 { - repulsingForce = repulsingForce / distance; + if (this._nodeInActiveArea(parentNode)) { + this._expelChildFromParent(parentNode,containedNodeId,recursive,force,openAll); + } } - fx = dx * repulsingForce; - fy = dy * repulsingForce; - - node1.fx -= fx; - node1.fy -= fy; - node2.fx += fx; - node2.fy += fy; + } } } } }; - /** - * this function calculates the effects of the springs in the case of unsmooth curves. + * 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. + * + * @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._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; - - - for (var i = 0; i < nodeIndices.length; i++) { - var node1 = nodes[nodeIndices[i]]; - node1.springFx = 0; - node1.springFy = 0; - } + 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(); - // 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.customLength ? edge.length : this.constants.physics.springLength; - // this implies that the edges between big clusters are longer - edgeLength += (edge.to.clusterSize + edge.from.clusterSize - 2) * this.constants.clustering.edgeGrowth; + // put the child node back in the global nodes object + this.nodes[containedNodeId] = childNode; - dx = (edge.from.x - edge.to.x); - dy = (edge.from.y - edge.to.y); - distance = Math.sqrt(dx * dx + dy * dy); + // release the contained edges from this childNode back into the global edges + this._releaseContainedEdges(parentNode,childNode); - if (distance == 0) { - distance = 0.01; - } + // reconnect rerouted edges to the childNode + this._connectEdgeBackToChild(parentNode,childNode); - // the 1/distance is so the fx and fy can be calculated without sine or cosine. - springForce = this.constants.physics.springConstant * (edgeLength - distance) / distance; + // validate all edges in dynamicEdges + this._validateEdges(parentNode); - fx = dx * springForce; - fy = dy * springForce; + // undo the changes from the clustering operation on the parent node + parentNode.mass -= childNode.mass; + parentNode.clusterSize -= childNode.clusterSize; + parentNode.fontSize = Math.min(this.constants.clustering.maxFontSize, this.constants.nodes.fontSize + this.constants.clustering.fontSizeMultiplier*parentNode.clusterSize); + parentNode.dynamicEdgesLength = parentNode.dynamicEdges.length; + // 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()); + // remove node from the list + delete parentNode.containedNodes[containedNodeId]; - 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; - } + // 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(); + } - // 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)); + this._repositionBezierNodes(childNode); + // this._repositionBezierNodes(parentNode); - node.fx += springFx; - node.fy += springFy; - } + // remove the clusterSession from the child node + childNode.clusterSession = 0; - // 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; + // recalculate the size of the node on the next time the node is rendered + parentNode.clearSizeCache(); - for (i = 0; i < nodeIndices.length; i++) { - var node = nodes[nodeIndices[i]]; - node.fx -= correctionFx; - node.fy -= correctionFy; + // 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); + } }; -/***/ }, -/* 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. + * position the bezier nodes at the center of the edges * + * @param node * @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); + exports._repositionBezierNodes = function(node) { + for (var i = 0; i < node.dynamicEdges.length; i++) { + node.dynamicEdges[i].positionBezierNode(); + } + }; - var barnesHutTree = this.barnesHutTree; - // place the nodes one by one recursively - for (var i = 0; i < nodeCount; i++) { - node = nodes[nodeIndices[i]]; - // 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); - } + /** + * 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 + */ + exports._formClusters = function(force) { + if (force == false) { + this._formClustersByZoom(); + } + else { + this._forceClustersByZoom(); } }; /** - * 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. + * This function handles the clustering by zooming out, this is based on a minimum edge distance * - * @param parentBranch - * @param node * @private */ - exports._getForceContribution = function(parentBranch,node) { - // we get no force contribution from an empty region - if (parentBranch.childrenCount > 0) { - var dx,dy,distance; + exports._formClustersByZoom = function() { + var dx,dy,length, + minLength = this.constants.clustering.clusterEdgeThreshold/this.scale; - // 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); + // 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); - // 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.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; + + if (length < minLength) { + // first check which node is larger + var parentNode = edge.from; + var childNode = edge.to; + if (edge.to.mass > edge.from.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); + } } - var gravityForce = this.constants.physics.barnesHut.gravitationalConstant * parentBranch.mass * node.mass / (distance * distance * distance); - var fx = dx * gravityForce; - var fy = dy * gravityForce; - node.fx += fx; - node.fy += fy; } } } @@ -26858,4044 +27979,4382 @@ return /******/ (function(modules) { // webpackBootstrap }; /** - * This function constructs the barnesHut tree recursively. It creates the root, splits it and starts placing the nodes. + * This function forces the network to cluster all nodes with only one connecting edge to their + * connected node. * - * @param nodes - * @param nodeIndices * @private */ - exports._formBarnesHutTree = function(nodes,nodeIndices) { - var node; - var nodeCount = nodeIndices.length; - - 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 (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 - + 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]; - 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); + // 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]; - // 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 + // group to the largest node + if (childNode.id != parentNode.id) { + if (parentNode.mass > childNode.mass) { + this._addToCluster(parentNode,childNode,true); + } + else { + this._addToCluster(childNode,parentNode,true); + } + } + } } - }; - this._splitBranch(barnesHutTree.root); - - // place the nodes one by one recursively - for (i = 0; i < nodeCount; i++) { - node = nodes[nodeIndices[i]]; - this._placeInTree(barnesHutTree.root,node); } - - // make global - this.barnesHutTree = barnesHutTree }; /** - * this updates the mass of a branch. this is increased by adding a node. + * To keep the nodes of roughly equal size we normalize the cluster levels. + * This function clusters a node to its smallest connected neighbour. * - * @param parentBranch * @param node * @private */ - exports._updateBranchMass = function(parentBranch, node) { - var totalMass = parentBranch.mass + node.mass; - var totalMassInv = 1/totalMass; - - parentBranch.centerOfMass.x = parentBranch.centerOfMass.x * parentBranch.mass + node.x * node.mass; - parentBranch.centerOfMass.x *= totalMassInv; + 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; + } - parentBranch.centerOfMass.y = parentBranch.centerOfMass.y * parentBranch.mass + node.y * node.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; + if (neighbour != null && smallestNeighbour > neighbour.clusterSessions.length) { + smallestNeighbour = neighbour.clusterSessions.length; + smallestNeighbourNode = neighbour; + } + } + } + if (neighbour != null && this.nodes[neighbour.id] !== undefined) { + this._addToCluster(neighbour, node, true); + } }; /** - * determine in which branch the node will be placed. + * This function forms clusters from hubs, it loops over all nodes * - * @param parentBranch - * @param node - * @param skipMassUpdate + * @param {Boolean} force | Disregard zoom level + * @param {Boolean} onlyEqual | This only clusters a hub with a specific number of edges * @private */ - exports._placeInTree = function(parentBranch,node,skipMassUpdate) { - if (skipMassUpdate != true || skipMassUpdate === undefined) { - // update the mass of the branch. - this._updateBranchMass(parentBranch,node); + 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); + } } + }; - 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"); - } + /** + * 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; } - else { // in NE or SE - if (parentBranch.children.NW.range.maxY > node.y) { // in NE - this._placeInRegion(parentBranch,node,"NE"); + // 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); } - else { // in SE - this._placeInRegion(parentBranch,node,"SE"); + + // 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; + } + } + } + } + } + } + + // 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); + } + } + } } } }; + /** - * actually place the node in a region (or branch) + * This function adds the child node to the parent node, creating a cluster if it is not already. * - * @param parentBranch - * @param node - * @param region + * @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._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; + 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); + } + else { + this._connectEdgeToCluster(parentNode,childNode,edge); + } + } + // 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.mass; + childNode.clusterSession = this.clusterSession; + parentNode.mass += childNode.mass; + parentNode.clusterSize += childNode.clusterSize; + parentNode.fontSize = Math.min(this.constants.clustering.maxFontSize, this.constants.nodes.fontSize + this.constants.clustering.fontSizeMultiplier*parentNode.clusterSize); + + // 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 } + + // 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 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 + * 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._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"); + 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 (containedNode != null) { - this._placeInTree(parentBranch,containedNode); + // 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; } }; /** - * 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 adds an edge from the childNode to the contained edges of the parent node * - * @param parentBranch - * @param region - * @param parentRange + * @param parentNode | Node object + * @param childNode | Node object + * @param edge | Edge object * @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; + 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]; - 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 - }; + // 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; + } + } }; - /** - * This function is for debugging purposed, it draws the tree. + * 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 ctx - * @param color + * @param {Node} parentNode | Node object + * @param {Node} childNode | Node object + * @param {Edge} edge | Edge object * @private */ - exports._drawTree = function(ctx,color) { - if (this.barnesHutTree !== undefined) { + 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 - ctx.lineWidth = 1; + edge.originalFromId.push(childNode.id); + edge.from = parentNode; + edge.fromId = parentNode.id; + } - this._drawBranch(this.barnesHutTree.root,ctx,color); + this._addToReroutedEdges(parentNode,childNode,edge); } }; /** - * This function is for debugging purposes. It draws the branches recursively. + * 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 branch - * @param ctx - * @param color + * @param parentNode + * @param childNode * @private */ - exports._drawBranch = function(branch,ctx,color) { - if (color === undefined) { - color = "#FF0000"; - } - - 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); + 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); + } } - ctx.strokeStyle = color; - ctx.beginPath(); - ctx.moveTo(branch.range.minX,branch.range.minY); - ctx.lineTo(branch.range.maxX,branch.range.minY); - ctx.stroke(); - - ctx.beginPath(); - ctx.moveTo(branch.range.maxX,branch.range.minY); - ctx.lineTo(branch.range.maxX,branch.range.maxY); - ctx.stroke(); - - 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(); - - /* - if (branch.mass > 0) { - ctx.circle(branch.centerOfMass.x, branch.centerOfMass.y, 3*branch.mass); - ctx.stroke(); - } - */ }; -/***/ }, -/* 55 */ -/***/ function(module, exports, __webpack_require__) { - /** - * Creation of the ClusterMixin var. + * This adds an edge from the childNode to the rerouted edges of the parent node * - * This contains all the functions the Network object can use to employ clustering + * @param parentNode | Node object + * @param childNode | Node object + * @param edge | Edge object + * @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 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 edge becomes part of the dynamicEdges of the cluster node + parentNode.dynamicEdges.push(edge); + }; - // 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(); - }; /** - * This function clusters until the initialMaxNodes has been reached + * This function connects an edge that was connected to a cluster node back to the child node. * - * @param {Number} maxNumberOfNodes - * @param {Boolean} reposition + * @param parentNode | Node object + * @param childNode | Node object + * @private */ - exports.clusterToFit = function(maxNumberOfNodes, reposition) { - var numberOfNodes = this.nodeIndices.length; + 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; + } - var maxLevels = 50; - var level = 0; + // append this edge to the list of edges connecting to the childnode + childNode.dynamicEdges.push(edge); - // 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 + // 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; + } + } } - - 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(); + // remove the entry from the rerouted edges + delete parentNode.reroutedEdges[childNode.id]; } - this._updateCalculationNodes(); }; + /** - * This function can be called to open up a specific cluster. It is only called by - * It will unpack the cluster back one level. + * 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 node | Node object: cluster to open. + * @param parentNode | Node object + * @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; - - // we decluster until we reach a decent number of nodes - while ((this.nodeIndices.length < this.constants.clustering.initialMaxNodes) && (level < 10)) { - this.decreaseClusterLevel(); - level += 1; + 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); } - - } - 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 calls the updateClustes with default arguments + * 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 {Node} parentNode | + * @param {Node} childNode | + * @private */ - exports.updateClustersDefault = function() { - if (this.constants.clustering.enabled == true) { - this.updateClusters(0,false,false); + 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; + + // 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]; + }; - /** - * 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.increaseClusterLevel = function() { - this.updateClusters(-1,false,true); - }; - /** - * 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.decreaseClusterLevel = function() { - this.updateClusters(1,false,true); - }; + // ------------------- UTILITY FUNCTIONS ---------------------------- // /** - * 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 updates the node labels for all nodes (for debugging purposes) */ - 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(); + 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),"]"); + } + } } - // 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(); + // 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); + } + } } } - 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(); - } + // /* Debug Override */ + // for (nodeId in this.nodes) { + // if (this.nodes.hasOwnProperty(nodeId)) { + // node = this.nodes[nodeId]; + // node.label = String(node.level); + // } + // } - // we now reduce chains. - if (this.previousScale > this.scale || zoomDirection == -1) { // zoom out - this.handleChains(); - this._updateNodeIndexList(); - } + }; - this.previousScale = this.scale; - // rest of the update the index list, dynamic edges and labels - this._updateDynamicEdges(); - this.updateLabels(); + /** + * 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.normalizeClusterLevels = function() { + var maxLevel = 0; + var minLevel = 1e9; + var clusterLevel = 0; + var nodeId; - // 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(); + // 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;} + } } - 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(); + 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._updateCalculationNodes(); }; + + /** - * This function handles the chains. It is called on every updateClusters(). + * This function determines if the cluster we want to decluster is in the active area + * this means around the zoom center + * + * @param {Node} node + * @returns {boolean} + * @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._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 functions starts clustering by hubs - * The minimum hub threshold is set globally + * 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. * - * @private */ - exports._aggregateHubs = function(force) { - this._getHubSize(); - this._formClustersByHub(force,false); + 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.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 fired by keypress. It forces hubs to form. + * 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%) * + * @private */ - exports.forceAggregateHubs = function(doNotStart) { - var isMovingBeforeClustering = this.moving; - var amountOfNodes = this.nodeIndices.length; - - this._aggregateHubs(true); + exports._getHubSize = function() { + var average = 0; + var averageSquared = 0; + var hubCounter = 0; + var largestHub = 0; - // update the index list, dynamic edges and labels - this._updateNodeIndexList(); - this._updateDynamicEdges(); - this.updateLabels(); + for (var i = 0; i < this.nodeIndices.length; i++) { - // if a cluster was formed, we increase the clusterSession - if (this.nodeIndices.length != amountOfNodes) { - this.clusterSession += 1; + 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; } + average = average / hubCounter; + averageSquared = averageSquared / hubCounter; - 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(); - } + 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; } + + // console.log("average",average,"averageSQ",averageSquared,"var",variance,"std",standardDeviation); + // console.log("hubThreshold:",this.hubThreshold); }; + /** - * If a cluster takes up more than a set percentage of the screen, open the cluster + * 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. * + * @param {Number} fraction | between 0 and 1, the percentage of chains to reduce * @private */ - exports._openClustersBySize = function() { + 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)) { - 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); + 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 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. + * 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. * * @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._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; }; - /** - * 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; - // 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]; +/***/ }, +/* 50 */ +/***/ function(module, exports, __webpack_require__) { - // 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); - } - } - } - } - } - } - }; + var util = __webpack_require__(1); /** - * ONLY CALLED FROM _expandClusterNode + * Creation of the SectorMixin var. * - * 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 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 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} 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._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.mass -= childNode.mass; - parentNode.clusterSize -= childNode.clusterSize; - parentNode.fontSize = Math.min(this.constants.clustering.maxFontSize, this.constants.nodes.fontSize + this.constants.clustering.fontSizeMultiplier*parentNode.clusterSize); - parentNode.dynamicEdgesLength = parentNode.dynamicEdges.length; - - // 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()); - - // 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._repositionBezierNodes(childNode); - // this._repositionBezierNodes(parentNode); - - // remove the clusterSession from the child node - childNode.clusterSession = 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; + }; - // 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; + /** + * /** + * 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); } - - // check if a further expansion step is possible if recursivity is enabled - if (recursive == true) { - this._expandClusterNode(childNode,recursive,force,openAll); + else { + this._switchToFrozenSector(sectorId); } }; /** - * position the bezier nodes at the center of the edges + * This function sets the global references to nodes, edges and nodeIndices back to + * those of the supplied active sector. * - * @param node + * @param sectorId * @private */ - exports._repositionBezierNodes = function(node) { - for (var i = 0; i < node.dynamicEdges.length; i++) { - node.dynamicEdges[i].positionBezierNode(); - } + 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 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 + * This function sets the global references to nodes, edges and nodeIndices back to + * those of the supplied active sector. * * @private - * @param {Boolean} force */ - exports._formClusters = function(force) { - if (force == false) { - this._formClustersByZoom(); - } - else { - this._forceClustersByZoom(); - } + exports._switchToSupportSector = function() { + this.nodeIndices = this.sectors["support"]["nodeIndices"]; + this.nodes = this.sectors["support"]["nodes"]; + this.edges = this.sectors["support"]["edges"]; }; /** - * This function handles the clustering by zooming out, this is based on a minimum edge distance + * This function sets the global references to nodes, edges and nodeIndices back to + * those of the supplied frozen sector. * + * @param sectorId * @private */ - 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.mass > edge.from.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); - } - } - } - } - } - } + 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 function forces the network to cluster all nodes with only one connecting edge to their - * connected node. + * This function sets the global references to nodes, edges and nodeIndices back to + * those of the currently active sector. * * @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]; - - // 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.mass > childNode.mass) { - this._addToCluster(parentNode,childNode,true); - } - else { - this._addToCluster(childNode,parentNode,true); - } - } - } - } - } + exports._loadLatestSector = function() { + this._switchToSector(this._sector()); }; /** - * To keep the nodes of roughly equal size we normalize the cluster levels. - * This function clusters a node to its smallest connected neighbour. + * This function returns the currently active sector Id * - * @param node + * @returns {String} * @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; - } + exports._sector = function() { + return this.activeSector[this.activeSector.length-1]; + }; - if (neighbour != null && smallestNeighbour > neighbour.clusterSessions.length) { - smallestNeighbour = neighbour.clusterSessions.length; - smallestNeighbourNode = neighbour; - } - } + /** + * 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 (neighbour != null && this.nodes[neighbour.id] !== undefined) { - this._addToCluster(neighbour, node, true); + else { + throw new TypeError('there are not enough sectors in the this.activeSector array.'); } }; /** - * This function forms clusters from hubs, it loops over all nodes + * 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 {Boolean} force | Disregard zoom level - * @param {Boolean} onlyEqual | This only clusters a hub with a specific number of edges + * @param newId * @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._setActiveSector = function(newId) { + this.activeSector.push(newId); }; + /** - * This function forms a cluster from a specific preselected hub node + * We remove the currently active sector id from the active sector stack. This happens when + * we reactivate the previously active sector * - * @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; + exports._forgetLastSector = function() { + this.activeSector.pop(); + }; - // 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); + /** + * 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._createNewSector = function(newId) { + // create the new sector + this.sectors["active"][newId] = {"nodes":{}, + "edges":{}, + "nodeIndices":[], + "formationScale": this.scale, + "drawingNode": undefined}; - if (length < minLength) { - allowCluster = true; - break; - } - } - } + // 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; + }; - // 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); - } - } - } - } - } + + /** + * 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._deleteActiveSector = function(sectorId) { + delete this.sectors["active"][sectorId]; }; + /** + * 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._deleteFrozenSector = function(sectorId) { + delete this.sectors["frozen"][sectorId]; + }; + /** - * This function adds the child node to the parent node, creating a cluster if it is not already. + * 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 | 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 sectorId * @private */ - exports._addToCluster = function(parentNode, childNode, force) { - // join child node in the parent node - parentNode.containedNodes[childNode.id] = childNode; + exports._freezeSector = function(sectorId) { + // we move the set references from the active to the frozen stack. + this.sectors["frozen"][sectorId] = this.sectors["active"][sectorId]; - // 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 = []; + // we have moved the sector data into the frozen set, we now remove it from the active set + this._deleteActiveSector(sectorId); + }; - // remove circular edges from clusters - this._containCircularEdgesFromNode(parentNode,childNode); + /** + * This is the reverse operation of _freezeSector. Activating means moving the sector from the "frozen" + * object to the "active" object. + * + * @param sectorId + * @private + */ + exports._activateSector = function(sectorId) { + // we move the set references from the frozen to the active stack. + this.sectors["active"][sectorId] = this.sectors["frozen"][sectorId]; - // remove the childNode from the global nodes object - delete this.nodes[childNode.id]; + // we have moved the sector data into the active set, we now remove it from the frozen stack + this._deleteFrozenSector(sectorId); + }; - // update the properties of the child and parent - var massBefore = parentNode.mass; - childNode.clusterSession = this.clusterSession; - parentNode.mass += childNode.mass; - parentNode.clusterSize += childNode.clusterSize; - parentNode.fontSize = Math.min(this.constants.clustering.maxFontSize, this.constants.nodes.fontSize + this.constants.clustering.fontSizeMultiplier*parentNode.clusterSize); - // 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); + /** + * 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]; + } } - // 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 + // 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]; + } } - // 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; + // merge the nodeIndices + for (var i = 0; i < this.nodeIndices.length; i++) { + this.sectors["frozen"][sectorId]["nodeIndices"].push(this.nodeIndices[i]); + } }; /** - * 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(). + * 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 */ - exports._updateDynamicEdges = function() { - for (var i = 0; i < this.nodeIndices.length; i++) { - var node = this.nodes[this.nodeIndices[i]]; - node.dynamicEdgesLength = node.dynamicEdges.length; - - // 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; - } + exports._collapseThisToSingleCluster = function() { + this.clusterToFit(1,false); }; /** - * This adds an edge from the childNode to the contained edges of the parent node + * We create a new active sector from the node that we want to open. * - * @param parentNode | Node object - * @param childNode | Node object - * @param edge | Edge object + * @param node * @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); + exports._addSector = function(node) { + // this is the currently active sector + var sector = this._sector(); - // remove the edge from the global edges object - delete this.edges[edge.id]; + // // 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!!"); + // } - // 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; - } - } + // 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]; + + var unqiueIdentifier = util.randomUUID(); + + // we fully freeze the currently active sector + this._freezeSector(sector); + + // 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); + + // 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 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. + * 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. * - * @param {Node} parentNode | Node object - * @param {Node} childNode | Node object - * @param {Edge} edge | Edge object * @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 + exports._collapseSector = function() { + // the currently active sector + var sector = this._sector(); - edge.originalFromId.push(childNode.id); - edge.from = parentNode; - edge.fromId = parentNode.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(); - this._addToReroutedEdges(parentNode,childNode,edge); + // 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); + + // 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); + + // we load the references from the newly active sector into the global references + this._switchToSector(previousSector); + + // 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(); + } } }; - /** - * If a node is connected to itself, a circular edge is drawn. When clustering we want to contain - * these edges inside of the cluster. + /** + * This runs a function in all active sectors. This is used in _redraw() and the _initializeForceCalculation(). * - * @param parentNode - * @param childNode + * @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._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._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 adds an edge from the childNode to the rerouted edges of the parent node + * This runs a function in all active sectors. This is used in _redraw() and the _initializeForceCalculation(). * - * @param parentNode | Node object - * @param childNode | Node object - * @param edge | Edge object + * @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._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] = []; + exports._doInSupportSector = function(runFunction,argument) { + if (argument === undefined) { + this._switchToSupportSector(); + this[runFunction](); } - parentNode.reroutedEdges[childNode.id].push(edge); - - // this edge becomes part of the dynamicEdges of the cluster node - parentNode.dynamicEdges.push(edge); - }; - + 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); + } + } + // we revert the global references back to our active sector + this._loadLatestSector(); + }; /** - * This function connects an edge that was connected to a cluster node back to the child node. + * This runs a function in all frozen sectors. This is used in the _redraw(). * - * @param parentNode | Node object - * @param childNode | Node object + * @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._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; + 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](); } - - // 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; + } + } + 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); } } } - // remove the entry from the rerouted edges - delete parentNode.reroutedEdges[childNode.id]; } + this._loadLatestSector(); }; /** - * 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 + * This runs a function in all sectors. This is used in the _redraw(). * - * @param parentNode | Node object + * @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._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._doInAllSectors = function(runFunction,argument) { + var args = Array.prototype.splice.call(arguments, 1); + if (argument === undefined) { + this._doInAllActiveSectors(runFunction); + this._doInAllFrozenSectors(runFunction); + } + 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 function released the contained edges back into the global domain and puts them back into the - * dynamic edges of both parent and child. + * 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. * - * @param {Node} parentNode | - * @param {Node} childNode | * @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; - - // 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]; - + exports._clearNodeIndexList = function() { + var sector = this._sector(); + this.sectors["active"][sector]["nodeIndices"] = []; + this.nodeIndices = this.sectors["active"][sector]["nodeIndices"]; }; - - - // ------------------- UTILITY FUNCTIONS ---------------------------- // - - /** - * This updates the node labels for all nodes (for debugging purposes) + * Draw the encompassing sector node + * + * @param ctx + * @param sectorType + * @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._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) { - // 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); + 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); } } } + }; - // /* Debug Override */ - // for (nodeId in this.nodes) { - // if (this.nodes.hasOwnProperty(nodeId)) { - // node = this.nodes[nodeId]; - // node.label = String(node.level); - // } - // } - + exports._drawAllSectorNodes = function(ctx) { + this._drawSectorNodes(ctx,"frozen"); + this._drawSectorNodes(ctx,"active"); + this._loadLatestSector(); }; +/***/ }, +/* 51 */ +/***/ function(module, exports, __webpack_require__) { + + var Node = __webpack_require__(36); + /** - * 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. + * This function can be called from the _doInAllSectors function + * + * @param object + * @param overlappingNodes + * @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;} - } - } - - 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]); - } + 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._updateNodeIndexList(); - this._updateDynamicEdges(); - // if a cluster was formed, we increase the clusterSession - if (this.nodeIndices.length != amountOfNodes) { - this.clusterSession += 1; - } } }; + /** + * 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; + }; /** - * This function determines if the cluster we want to decluster is in the active area - * this means around the zoom center + * Return a position object in canvasspace from a single point in screenspace * - * @param {Node} node - * @returns {boolean} + * @param pointer + * @returns {{left: number, top: number, right: number, bottom: number}} * @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._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 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. + * Get the top node at the a specific point (like a click) * + * @param {{x: Number, y: Number}} pointer + * @return {Node | null} node + * @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.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._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; } }; /** - * 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%) - * + * 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._getHubSize = function() { - var average = 0; - var averageSquared = 0; - var hubCounter = 0; - var largestHub = 0; - - for (var i = 0; i < this.nodeIndices.length; i++) { - - var node = this.nodes[this.nodeIndices[i]]; - if (node.dynamicEdgesLength > largestHub) { - largestHub = node.dynamicEdgesLength; + 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); + } } - 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); + /** + * 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._getAllEdgesOverlappingWith = function (object) { + var overlappingEdges = []; + this._doInAllActiveSectors("_getEdgesOverlappingWith",object,overlappingEdges); + return overlappingEdges; + }; - this.hubThreshold = Math.floor(average + 2*standardDeviation); + /** + * 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 pointer + * @returns {null} + * @private + */ + exports._getEdgeAt = function(pointer) { + var positionObject = this._pointerToPositionObject(pointer); + var overlappingEdges = this._getAllEdgesOverlappingWith(positionObject); - // always have at least one to cluster - if (this.hubThreshold > largestHub) { - this.hubThreshold = largestHub; + if (overlappingEdges.length > 0) { + return this.edges[overlappingEdges[overlappingEdges.length - 1]]; + } + else { + return null; } - - // 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. + * Add object to the selection array. * - * @param {Number} fraction | between 0 and 1, the percentage of chains to reduce + * @param obj * @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._addToSelection = function(obj) { + if (obj instanceof Node) { + this.selectionObj.nodes[obj.id] = obj; + } + else { + this.selectionObj.edges[obj.id] = obj; } }; /** - * 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. + * Add object to the selection array. * + * @param obj * @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._addToHover = function(obj) { + if (obj instanceof Node) { + this.hoverObj.nodes[obj.id] = obj; + } + else { + this.hoverObj.edges[obj.id] = obj; } - return chains/total; }; -/***/ }, -/* 56 */ -/***/ function(module, exports, __webpack_require__) { - - var util = __webpack_require__(1); - /** - * Creation of the SectorMixin var. + * Remove a single option from selection. * - * 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. + * @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]; + } + }; /** - * 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. + * Unselect all. The selectionObj is useful for this. * + * @param {Boolean} [doNotTrigger] | ignore trigger * @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._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()); + } + }; /** - * /** - * 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 + * Unselect all clusters. The selectionObj is useful for this. * - * @param {String} sectorId - * @param {String} [sectorType] | "active" or "frozen" + * @param {Boolean} [doNotTrigger] | ignore trigger * @private */ - exports._switchToSector = function(sectorId, sectorType) { - if (sectorType === undefined || sectorType == "active") { - this._switchToActiveSector(sectorId); + exports._unselectClusters = function(doNotTrigger) { + if (doNotTrigger === undefined) { + doNotTrigger = false; } - else { - this._switchToFrozenSector(sectorId); + + 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]); + } + } + } + + if (doNotTrigger == false) { + this.emit('select', this.getSelection()); } }; /** - * This function sets the global references to nodes, edges and nodeIndices back to - * those of the supplied active sector. + * return the number of selected nodes * - * @param sectorId + * @returns {number} * @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._getSelectedNodeCount = function() { + var count = 0; + for (var nodeId in this.selectionObj.nodes) { + if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { + count += 1; + } + } + return count; }; - /** - * This function sets the global references to nodes, edges and nodeIndices back to - * those of the supplied active sector. + * return the selected node * + * @returns {number} * @private */ - exports._switchToSupportSector = function() { - this.nodeIndices = this.sectors["support"]["nodeIndices"]; - this.nodes = this.sectors["support"]["nodes"]; - this.edges = this.sectors["support"]["edges"]; + exports._getSelectedNode = function() { + for (var nodeId in this.selectionObj.nodes) { + if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { + return this.selectionObj.nodes[nodeId]; + } + } + return null; }; - /** - * This function sets the global references to nodes, edges and nodeIndices back to - * those of the supplied frozen sector. + * return the selected edge * - * @param sectorId + * @returns {number} * @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._getSelectedEdge = function() { + for (var edgeId in this.selectionObj.edges) { + if (this.selectionObj.edges.hasOwnProperty(edgeId)) { + return this.selectionObj.edges[edgeId]; + } + } + return null; }; /** - * This function sets the global references to nodes, edges and nodeIndices back to - * those of the currently active sector. + * return the number of selected edges * + * @returns {number} * @private */ - exports._loadLatestSector = function() { - this._switchToSector(this._sector()); + 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 returns the currently active sector Id + * return the number of selected objects. * - * @returns {String} + * @returns {number} * @private */ - exports._sector = function() { - return this.activeSector[this.activeSector.length-1]; + 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; }; - /** - * This function returns the previously active sector Id + * Check if anything is selected * - * @returns {String} + * @returns {boolean} * @private */ - exports._previousSector = function() { - if (this.activeSector.length > 1) { - return this.activeSector[this.activeSector.length-2]; + exports._selectionIsEmpty = function() { + for(var nodeId in this.selectionObj.nodes) { + if(this.selectionObj.nodes.hasOwnProperty(nodeId)) { + return false; + } } - else { - throw new TypeError('there are not enough sectors in the this.activeSector array.'); + for(var edgeId in this.selectionObj.edges) { + if(this.selectionObj.edges.hasOwnProperty(edgeId)) { + return false; + } } + return true; }; /** - * 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. + * check if one of the selected nodes is a cluster. * - * @param newId + * @returns {boolean} * @private */ - exports._setActiveSector = function(newId) { - this.activeSector.push(newId); + 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; }; - /** - * We remove the currently active sector id from the active sector stack. This happens when - * we reactivate the previously active sector + * select the edges connected to the node that is being selected * + * @param {Node} node * @private */ - exports._forgetLastSector = function() { - this.activeSector.pop(); + 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 creates a new active sector with the supplied newId. This newId - * is the expanding node id. + * select the edges connected to the node that is being selected * - * @param {String} newId | Id of the new active sector + * @param {Node} node * @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._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 removes the currently active sector. This is called when we create a new - * active sector. + * unselect the edges connected to the node that is being selected * - * @param {String} sectorId | Id of the active sector that will be removed + * @param {Node} node * @private */ - exports._deleteActiveSector = function(sectorId) { - delete this.sectors["active"][sectorId]; + 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 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._deleteFrozenSector = function(sectorId) { - delete this.sectors["frozen"][sectorId]; - }; /** - * Freezing an active sector means moving it from the "active" object to the "frozen" object. - * We copy the references, then delete the active entree. + * 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 sectorId + * @param {Node || Edge} object + * @param {Boolean} append + * @param {Boolean} [doNotTrigger] | ignore trigger * @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._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); + } - // we have moved the sector data into the frozen set, we now remove it from the active set - this._deleteActiveSector(sectorId); + if (doNotTrigger == false) { + this.emit('select', this.getSelection()); + } }; /** - * This is the reverse operation of _freezeSector. Activating means moving the sector from the "frozen" - * object to the "active" object. + * 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 sectorId + * @param {Node || Edge} object * @private */ - 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._blurObject = function(object) { + if (object.hover == true) { + object.hover = false; + this.emit("blurNode",{node:object.id}); + } }; - /** - * 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. + * 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 sectorId + * @param {Node || Edge} object * @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]; - } - } - - // 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._hoverObject = function(object) { + if (object.hover == false) { + object.hover = true; + this._addToHover(object); + if (object instanceof Node) { + this.emit("hoverNode",{node:object.id}); } } - - // merge the nodeIndices - for (var i = 0; i < this.nodeIndices.length; i++) { - this.sectors["frozen"][sectorId]["nodeIndices"].push(this.nodeIndices[i]); + if (object instanceof Node) { + this._hoverConnectedEdges(object); } }; /** - * 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. + * 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._collapseThisToSingleCluster = function() { - this.clusterToFit(1,false); + exports._handleTouch = function(pointer) { }; /** - * We create a new active sector from the node that we want to open. + * handles the selection part of the tap; * - * @param node + * @param {Object} pointer * @private */ - 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]; - - var unqiueIdentifier = util.randomUUID(); - - // we fully freeze the currently active sector - this._freezeSector(sector); - - // 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); - - // 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; + 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(); }; /** - * 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. + * handles the selection part of the double tap and opens a cluster if needed * + * @param {Object} pointer * @private */ - exports._collapseSector = function() { - // the currently active sector - var sector = this._sector(); - - // 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(); - - // 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); - - // 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); - - // we load the references from the newly active sector into the global references - this._switchToSector(previousSector); - - // 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(); - } + 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 runs a function in all active sectors. This is used in _redraw() and the _initializeForceCalculation(). + * Handle the onHold selection part * - * @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 + * @param pointer * @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._handleOnHold = function(pointer) { + var node = this._getNodeAt(pointer); + if (node != null) { + this._selectObject(node,true); } 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); - } - } + var edge = this._getEdgeAt(pointer); + if (edge != null) { + this._selectObject(edge,true); } } - // we revert the global references back to our active sector - this._loadLatestSector(); + this._redraw(); }; /** - * This runs a function in all active sectors. This is used in _redraw() and the _initializeForceCalculation(). + * handle the onRelease event. These functions are here for the navigation controls module. * - * @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 + * @private */ - exports._doInSupportSector = function(runFunction,argument) { - if (argument === undefined) { - this._switchToSupportSector(); - this[runFunction](); - } - 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); + exports._handleOnRelease = function(pointer) { + + }; + + + + /** + * + * retrieve the currently selected objects + * @return {{nodes: Array., edges: Array.}} selection + */ + exports.getSelection = function() { + var nodeIds = this.getSelectedNodes(); + var edgeIds = this.getSelectedEdges(); + return {nodes:nodeIds, edges:edgeIds}; + }; + + /** + * + * 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); } } - // we revert the global references back to our active sector - this._loadLatestSector(); + return idArray }; - /** - * This runs a function in all frozen 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 + * retrieve the currently selected edges + * @return {Array} selection An array with the ids of the + * selected nodes. */ - 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 { - 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); - } - } + exports.getSelectedEdges = function() { + var idArray = []; + for(var edgeId in this.selectionObj.edges) { + if(this.selectionObj.edges.hasOwnProperty(edgeId)) { + idArray.push(edgeId); } } - this._loadLatestSector(); + return idArray; }; /** - * 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 + * select zero or more nodes + * @param {Number[] | String[]} selection An array with the ids of the + * selected nodes. */ - exports._doInAllSectors = function(runFunction,argument) { - var args = Array.prototype.splice.call(arguments, 1); - if (argument === undefined) { - this._doInAllActiveSectors(runFunction); - this._doInAllFrozenSectors(runFunction); - } - 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); + 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'); } + this._selectObject(node,true,true); } - }; + console.log("setSelection is deprecated. Please use selectNodes instead.") - /** - * 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.redraw(); }; /** - * Draw the encompassing sector node - * - * @param ctx - * @param sectorType - * @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._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) { + exports.selectNodes = function(selection, highlightEdges) { + var i, iMax, id; - this._switchToSector(sector,sectorType); + if (!selection || (selection.length == undefined)) + throw 'Selection must be an array with ids'; - 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); - } + // 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._drawAllSectorNodes = function(ctx) { - this._drawSectorNodes(ctx,"frozen"); - this._drawSectorNodes(ctx,"active"); - this._loadLatestSector(); - }; + /** + * 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; -/***/ }, -/* 57 */ -/***/ function(module, exports, __webpack_require__) { + if (!selection || (selection.length == undefined)) + throw 'Selection must be an array with ids'; - var Node = __webpack_require__(47); + // first unselect any selected node + this._unselectAll(true); - /** - * 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); - } + for (i = 0, iMax = selection.length; i < iMax; i++) { + id = selection[i]; + + var edge = this.edges[id]; + if (!edge) { + throw new RangeError('Edge with id "' + id + '" not found'); } + this._selectObject(edge,true,true,highlightEdges); } + 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 + * Validate the selection: remove ids of nodes which no longer exist * @private */ - exports._getAllNodesOverlappingWith = function (object) { - var overlappingNodes = []; - this._doInAllActiveSectors("_getNodesOverlappingWith",object,overlappingNodes); - return overlappingNodes; + 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]; + } + } + } }; - /** - * Return a position object in canvasspace from a single point in screenspace - * - * @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); - - return { - left: x, - top: y, - right: x, - bottom: y - }; - }; +/***/ }, +/* 52 */ +/***/ function(module, exports, __webpack_require__) { + var util = __webpack_require__(1); + var Node = __webpack_require__(36); + var Edge = __webpack_require__(33); /** - * Get the top node at the a specific point (like a click) + * clears the toolbar div element of children * - * @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); - - // 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; + exports._clearManipulatorBar = function() { + while (this.manipulationDiv.hasChildNodes()) { + this.manipulationDiv.removeChild(this.manipulationDiv.firstChild); } }; - /** - * 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 + * 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._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); - } + exports._restoreOverloadedFunctions = function() { + for (var functionName in this.cachedFunctions) { + if (this.cachedFunctions.hasOwnProperty(functionName)) { + this[functionName] = this.cachedFunctions[functionName]; } } }; - /** - * 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 + * Enable or disable edit-mode. + * * @private */ - exports._getAllEdgesOverlappingWith = function (object) { - var overlappingEdges = []; - this._doInAllActiveSectors("_getEdgesOverlappingWith",object,overlappingEdges); - return overlappingEdges; + 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 { + toolbar.style.display="none"; + closeDiv.style.display="none"; + editModeDiv.style.display="block"; + closeDiv.onclick = null; + } + this._createManipulatorBar() }; /** - * Place holder. To implement change the _getNodeAt to a _getObjectAt. Have the _getObjectAt call - * _getNodeAt and _getEdgesAt, then priortize the selection to user preferences. + * main function, creates the main toolbar. Removes functions bound to the select event. Binds all the buttons of the toolbar. * - * @param pointer - * @returns {null} * @private */ - exports._getEdgeAt = function(pointer) { - var positionObject = this._pointerToPositionObject(pointer); - var overlappingEdges = this._getAllEdgesOverlappingWith(positionObject); + exports._createManipulatorBar = function() { + // remove bound functions + if (this.boundFunction) { + this.off('select', this.boundFunction); + } - if (overlappingEdges.length > 0) { - return this.edges[overlappingEdges[overlappingEdges.length - 1]]; + 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 { - return null; + this.editModeDiv.innerHTML = "" + + "" + + "" + this.constants.labels['edit'] + ""; + var editModeButton = document.getElementById("network-manipulate-editModeButton"); + editModeButton.onclick = this._toggleEditMode.bind(this); } }; + /** - * Add object to the selection array. + * Create the toolbar for adding Nodes * - * @param obj * @private */ - exports._addToSelection = function(obj) { - if (obj instanceof Node) { - this.selectionObj.nodes[obj.id] = obj; - } - else { - this.selectionObj.edges[obj.id] = obj; + 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); }; + /** - * Add object to the selection array. + * create the toolbar to connect nodes * - * @param obj * @private */ - exports._addToHover = function(obj) { - if (obj instanceof Node) { - this.hoverObj.nodes[obj.id] = obj; - } - else { - this.hoverObj.edges[obj.id] = obj; + exports._createAddEdgeToolbar = function() { + // clear the toolbar + this._clearManipulatorBar(); + this._unselectAll(true); + this.freezeSimulation = true; + + if (this.boundFunction) { + this.off('select', this.boundFunction); } - }; + this._unselectAll(); + this.forceAppendSelection = false; + this.blockConnectingEdgeSelection = true; + + this.manipulationDiv.innerHTML = "" + + "" + + "" + this.constants.labels['back'] + " " + + "
" + + "" + + "" + this.constants.labels['linkDescription'] + ""; + + // 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._handleConnect.bind(this); + this.on('select', this.boundFunction); + + // temporarily overload functions + this.cachedFunctions["_handleTouch"] = this._handleTouch; + this.cachedFunctions["_handleOnRelease"] = this._handleOnRelease; + this._handleTouch = this._handleConnect; + this._handleOnRelease = this._finishConnect; + + // redraw to show the unselect + this._redraw(); + }; /** - * Remove a single option from selection. + * create the toolbar to edit edges * - * @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._createEditEdgeToolbar = function() { + // clear the toolbar + this._clearManipulatorBar(); + this.controlNodesActive = true; + + if (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'] + ""; + + // 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; + + // redraw to show the unselect + this._redraw(); }; + + + + /** - * Unselect all. The selectionObj is useful for 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. * - * @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(); - } - } - 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()); + 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(); }; /** - * Unselect all clusters. The selectionObj is useful for 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. * - * @param {Boolean} [doNotTrigger] | ignore trigger * @private */ - exports._unselectClusters = function(doNotTrigger) { - if (doNotTrigger === undefined) { - doNotTrigger = false; + 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(); + }; - 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._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(); } } - - if (doNotTrigger == false) { - this.emit('select', this.getSelection()); + else { + this.edgeBeingEdited._restoreControlNodes(); } + this.freezeSimulation = false; + this._redraw(); }; - /** - * return the number of selected 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. * - * @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._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(); + } } } - 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]; + 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(); } - return null; }; + /** - * return the selected edge - * - * @returns {number} - * @private + * Adds a node on the specified location */ - exports._getSelectedEdge = function() { - for (var edgeId in this.selectionObj.edges) { - if (this.selectionObj.edges.hasOwnProperty(edgeId)) { - return this.selectionObj.edges[edgeId]; + 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(); } } - return null; }; /** - * return the number of selected edges + * connect two nodes with a new edge. * - * @returns {number} * @private */ - exports._getSelectedEdgeCount = function() { - var count = 0; - for (var edgeId in this.selectionObj.edges) { - if (this.selectionObj.edges.hasOwnProperty(edgeId)) { - count += 1; + 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(); } } - return count; }; - /** - * return the number of selected objects. + * connect two nodes with a new edge. * - * @returns {number} * @private */ - exports._getSelectedObjectCount = function() { - var count = 0; - for(var nodeId in this.selectionObj.nodes) { - if(this.selectionObj.nodes.hasOwnProperty(nodeId)) { - count += 1; + 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)) { - count += 1; + else { + this.edgesData.update(defaultData); + this.moving = true; + this.start(); } } - return count; }; /** - * Check if anything is selected + * Create the toolbar to edit the selected node. The label and the color can be changed. Other colors are derived from the chosen color. * - * @returns {boolean} * @private */ - exports._selectionIsEmpty = function() { - for(var nodeId in this.selectionObj.nodes) { - if(this.selectionObj.nodes.hasOwnProperty(nodeId)) { - return false; + exports._editNode = function() { + if (this.triggerFunctions.edit && this.editMode == true) { + var node = this._getSelectedNode(); + var data = {id:node.id, + label: node.label, + group: node.group, + shape: node.shape, + color: { + background:node.color.background, + border:node.color.border, + highlight: { + background:node.color.highlight.background, + border:node.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(); + }); } - } - for(var edgeId in this.selectionObj.edges) { - if(this.selectionObj.edges.hasOwnProperty(edgeId)) { - return false; + else { + alert(this.constants.labels["editError"]); } } - return true; + else { + alert(this.constants.labels["editBoundError"]); + } }; + + /** - * check if one of the selected nodes is a cluster. + * delete everything in the selection * - * @returns {boolean} * @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; + 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 false; + }; + + +/***/ }, +/* 53 */ +/***/ function(module, exports, __webpack_require__) { + + var util = __webpack_require__(1); + + 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; }; /** - * select the edges connected to the node that is being selected + * 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. * - * @param {Node} node * @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._loadNavigationElements = function() { + this._cleanNavigation(); + + this.navigationDivs = {}; + var navigationDivs = ['up','down','left','right','zoomIn','zoomOut','zoomExtends']; + var navigationDivActions = ['_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 = 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]]); + this.navigationDivs[navigationDivs[i]].onmousedown = this[navigationDivActions[i]].bind(this); } + + document.onmouseup = this._stopMovement.bind(this); }; /** - * select the edges connected to the node that is being selected + * this stops all movement induced by the navigation buttons * - * @param {Node} node * @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._stopMovement = function() { + this._xStopMoving(); + this._yStopMoving(); + this._stopZoom(); }; /** - * unselect the edges connected to the node that is being 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. * - * @param {Node} node * @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._moveUp = function(event) { + this.yIncrement = this.constants.keyboard.speed.y; + this.start(); // if there is no node movement, the calculation wont be done + util.preventDefault(event); + if (this.navigationDivs) { + this.navigationDivs['up'].className += " active"; } }; - - /** - * 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 + * move the screen down * @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); + exports._moveDown = function(event) { + this.yIncrement = -this.constants.keyboard.speed.y; + this.start(); // if there is no node movement, the calculation wont be done + util.preventDefault(event); + if (this.navigationDivs) { + this.navigationDivs['down'].className += " active"; } + }; - 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()); + /** + * 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 + util.preventDefault(event); + if (this.navigationDivs) { + this.navigationDivs['left'].className += " active"; } }; /** - * 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 + * move the screen right * @private */ - exports._blurObject = function(object) { - if (object.hover == true) { - object.hover = false; - this.emit("blurNode",{node:object.id}); + exports._moveRight = function(event) { + this.xIncrement = -this.constants.keyboard.speed.y; + this.start(); // if there is no node movement, the calculation wont be done + util.preventDefault(event); + if (this.navigationDivs) { + this.navigationDivs['right'].className += " active"; } }; + /** - * 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 + * Zoom in, using the same method as the movement. * @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._zoomIn = function(event) { + this.zoomIncrement = this.constants.keyboard.speed.zoom; + this.start(); // if there is no node movement, the calculation wont be done + util.preventDefault(event); + if (this.navigationDivs) { + this.navigationDivs['zoomIn'].className += " active"; } }; /** - * 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 + * Zoom out * @private */ - exports._handleTouch = function(pointer) { + 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); + if (this.navigationDivs) { + this.navigationDivs['zoomOut'].className += " active"; + } }; /** - * handles the selection part of the tap; - * - * @param {Object} pointer + * Stop zooming and unhighlight the zoom controls * @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); - } - else { - this._unselectAll(); - } + exports._stopZoom = function() { + this.zoomIncrement = 0; + if (this.navigationDivs) { + this.navigationDivs['zoomIn'].className = this.navigationDivs['zoomIn'].className.replace(" active",""); + this.navigationDivs['zoomOut'].className = this.navigationDivs['zoomOut'].className.replace(" active",""); } - this.emit("click", this.getSelection()); - this._redraw(); }; /** - * handles the selection part of the double tap and opens a cluster if needed - * - * @param {Object} pointer + * Stop moving in the Y direction and unHighlight the up and down * @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._yStopMoving = function() { + this.yIncrement = 0; + if (this.navigationDivs) { + this.navigationDivs['up'].className = this.navigationDivs['up'].className.replace(" active",""); + this.navigationDivs['down'].className = this.navigationDivs['down'].className.replace(" active",""); } - this.emit("doubleClick", this.getSelection()); }; /** - * Handle the onHold selection part - * - * @param pointer + * Stop moving in the X direction and unHighlight left and right. * @private */ - exports._handleOnHold = function(pointer) { - var node = this._getNodeAt(pointer); - if (node != null) { - this._selectObject(node,true); + exports._xStopMoving = function() { + this.xIncrement = 0; + if (this.navigationDivs) { + this.navigationDivs['left'].className = this.navigationDivs['left'].className.replace(" active",""); + this.navigationDivs['right'].className = this.navigationDivs['right'].className.replace(" active",""); } - else { - var edge = this._getEdgeAt(pointer); - if (edge != null) { - this._selectObject(edge,true); + }; + + +/***/ }, +/* 54 */ +/***/ 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._redraw(); }; - /** - * handle the onRelease event. These functions are here for the navigation controls module. + * This is the main function to layout the nodes in a hierarchical way. + * It checks if the node details are supplied correctly * - * @private + * @private */ - exports._handleOnRelease = function(pointer) { + 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; + + 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(); - /** - * - * retrieve the currently selected objects - * @return {{nodes: Array., edges: Array.}} selection - */ - exports.getSelection = function() { - var nodeIds = this.getSelectedNodes(); - var edgeIds = this.getSelectedEdges(); - return {nodes:nodeIds, edges:edgeIds}; - }; + // place the nodes on the canvas. This also stablilizes the system. + this._placeNodesByHierarchy(distribution); - /** - * - * 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); + // start the simulation. + this.start(); } } - return idArray }; + /** + * This function places the nodes on the canvas based on the hierarchial distribution. * - * retrieve the currently selected edges - * @return {Array} selection An array with the ids of the - * selected nodes. + * @param {Object} distribution | obtained by the function this._getDistribution() + * @private */ - exports.getSelectedEdges = function() { - var idArray = []; - for(var edgeId in this.selectionObj.edges) { - if(this.selectionObj.edges.hasOwnProperty(edgeId)) { - idArray.push(edgeId); + 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); + } + } } } - return idArray; + + // stabilize the system after positioning. This function calls zoomExtent. + this._stabilize(); }; /** - * select zero or more nodes - * @param {Number[] | String[]} selection An array with the ids of the - * selected nodes. + * This function get the distribution of levels based on hubsize + * + * @returns {Object} + * @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]; + exports._getDistribution = function() { + var distribution = {}; + var nodeId, node, level; - var node = this.nodes[id]; - if (!node) { - throw new RangeError('Node with id "' + id + '" not found'); + // 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; + } + } + + // 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; + } } - this._selectObject(node,true,true); } - console.log("setSelection is deprecated. Please use selectNodes instead.") + // 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); + } + } - this.redraw(); + return distribution; }; /** - * 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] + * this function allocates nodes in levels based on the recursive branching from the largest hubs. + * + * @param hubsize + * @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); + exports._determineLevels = function(hubsize) { + var nodeId, node; - for (i = 0, iMax = selection.length; i < iMax; i++) { - id = selection[i]; + // determine hubs + for (nodeId in this.nodes) { + if (this.nodes.hasOwnProperty(nodeId)) { + node = this.nodes[nodeId]; + if (node.edges.length == hubsize) { + node.level = 0; + } + } + } - var node = this.nodes[id]; - if (!node) { - throw new RangeError('Node with id "' + id + '" not found'); + // 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._selectObject(node,true,true,highlightEdges); } - this.redraw(); }; /** - * select zero or more edges - * @param {Number[] | String[]} selection An array with the ids of the - * selected nodes. + * 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.selectEdges = function(selection) { - var i, iMax, id; + 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(); + }; - if (!selection || (selection.length == undefined)) - throw 'Selection must be an array with ids'; - // first unselect any selected node - this._unselectAll(true); + /** + * This is a recursively called function to enumerate the branches from the largest hubs and place the nodes + * on a X position that ensures there will be no overlap. + * + * @param edges + * @param parentId + * @param distribution + * @param parentLevel + * @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; + } - for (i = 0, iMax = selection.length; i < iMax; i++) { - id = selection[i]; + // 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; + } + } - var edge = this.edges[id]; - if (!edge) { - throw new RangeError('Edge with id "' + id + '" not found'); + 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); + } } - this._selectObject(edge,true,true,highlightEdges); } - this.redraw(); }; + /** - * Validate the selection: remove ids of nodes which no longer exist + * this function is called recursively to enumerate the barnches of the largest hubs and give each node a level. + * + * @param level + * @param edges + * @param parentId * @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]; + 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); } } } - for(var edgeId in this.selectionObj.edges) { - if(this.selectionObj.edges.hasOwnProperty(edgeId)) { - if (!this.edges.hasOwnProperty(edgeId)) { - delete this.selectionObj.edges[edgeId]; - } + }; + + + /** + * Unfix nodes + * + * @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; } } }; /***/ }, -/* 58 */ +/* 55 */ /***/ function(module, exports, __webpack_require__) { var util = __webpack_require__(1); - var Node = __webpack_require__(47); - var Edge = __webpack_require__(48); + var RepulsionMixin = __webpack_require__(57); + var HierarchialRepulsionMixin = __webpack_require__(58); + var BarnesHutMixin = __webpack_require__(59); /** - * clears the toolbar div element of children + * Toggling barnes Hut calculation on and off. * * @private */ - exports._clearManipulatorBar = function() { - while (this.manipulationDiv.hasChildNodes()) { - this.manipulationDiv.removeChild(this.manipulationDiv.firstChild); - } + exports._toggleBarnesHut = function () { + this.constants.physics.barnesHut.enabled = !this.constants.physics.barnesHut.enabled; + this._loadSelectedForceSolver(); + this.moving = true; + this.start(); }; + /** - * 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. + * This loads the node force solver based on the barnes hut or repulsion algorithm * * @private */ - exports._restoreOverloadedFunctions = function() { - for (var functionName in this.cachedFunctions) { - if (this.cachedFunctions.hasOwnProperty(functionName)) { - this[functionName] = this.cachedFunctions[functionName]; - } + exports._loadSelectedForceSolver = function () { + // this overloads the this._calculateNodeForces + if (this.constants.physics.barnesHut.enabled == true) { + this._clearMixin(RepulsionMixin); + this._clearMixin(HierarchialRepulsionMixin); + + 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; + + this._loadMixin(BarnesHutMixin); } - }; + else if (this.constants.physics.hierarchicalRepulsion.enabled == true) { + this._clearMixin(BarnesHutMixin); + this._clearMixin(RepulsionMixin); - /** - * Enable or disable edit-mode. - * - * @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); + 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 { - toolbar.style.display="none"; - closeDiv.style.display="none"; - editModeDiv.style.display="block"; - closeDiv.onclick = null; + 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._loadMixin(RepulsionMixin); } - this._createManipulatorBar() }; /** - * main function, creates the main toolbar. Removes functions bound to the select event. Binds all the buttons of the toolbar. + * 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._createManipulatorBar = function() { - // remove bound functions - if (this.boundFunction) { - this.off('select', this.boundFunction); + 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); + } - if (this.edgeBeingEdited !== undefined) { - this.edgeBeingEdited._disableControlNodes(); - this.edgeBeingEdited = undefined; - this.selectedControlNode = null; - this.controlNodesActive = false; + // we now start the force calculation + this._calculateForces(); } + }; - // 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'] +""; - } + /** + * Calculate the external forces acting on the nodes + * Forces are caused by: edges, repulsing forces between nodes, gravity + * @private + */ + 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(); - // 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.constants.physics.springConstant > 0) { + if (this.constants.smoothCurves.enabled == true && this.constants.smoothCurves.dynamic == true) { + this._calculateSpringForcesWithSupport(); } - if (this._selectionIsEmpty() == false) { - var deleteButton = document.getElementById("network-manipulate-delete"); - deleteButton.onclick = this._deleteSelected.bind(this); + else { + if (this.constants.physics.hierarchicalRepulsion.enabled == true) { + this._calculateHierarchicalSpringForces(); + } + else { + this._calculateSpringForces(); + } } - 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 + * 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._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'] + ""; + exports._updateCalculationNodes = function () { + if (this.constants.smoothCurves.enabled == true && this.constants.smoothCurves.dynamic == true) { + this.calculationNodes = {}; + this.calculationNodeIndices = []; - // bind the icon - var backButton = document.getElementById("network-manipulate-back"); - backButton.onclick = this._createManipulatorBar.bind(this); + 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); + } + } + } - // 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); + for (var idx in this.calculationNodes) { + if (this.calculationNodes.hasOwnProperty(idx)) { + this.calculationNodeIndices.push(idx); + } + } + } + else { + this.calculationNodes = this.nodes; + this.calculationNodeIndices = this.nodeIndices; + } }; /** - * create the toolbar to connect nodes + * this function applies the central gravity effect to keep groups from floating off * * @private */ - exports._createAddEdgeToolbar = function() { - // clear the toolbar - this._clearManipulatorBar(); - this._unselectAll(true); - this.freezeSimulation = true; - - if (this.boundFunction) { - this.off('select', this.boundFunction); - } - - this._unselectAll(); - this.forceAppendSelection = false; - this.blockConnectingEdgeSelection = true; + exports._calculateGravitationalForces = function () { + var dx, dy, distance, node, i; + var nodes = this.calculationNodes; + var gravity = this.constants.physics.centralGravity; + var gravityForce = 0; - this.manipulationDiv.innerHTML = "" + - "" + - "" + this.constants.labels['back'] + " " + - "
" + - "" + - "" + this.constants.labels['linkDescription'] + ""; + 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 icon - var backButton = document.getElementById("network-manipulate-back"); - backButton.onclick = this._createManipulatorBar.bind(this); + gravityForce = (distance == 0) ? 0 : (gravity / distance); + node.fx = dx * gravityForce; + node.fy = dy * gravityForce; + } + else { + node.fx = 0; + node.fy = 0; + } + } + }; - // 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); - // temporarily overload functions - this.cachedFunctions["_handleTouch"] = this._handleTouch; - this.cachedFunctions["_handleOnRelease"] = this._handleOnRelease; - this._handleTouch = this._handleConnect; - this._handleOnRelease = this._finishConnect; - // redraw to show the unselect - this._redraw(); - }; /** - * create the toolbar to edit edges + * this function calculates the effects of the springs in the case of unsmooth curves. * * @private */ - exports._createEditEdgeToolbar = function() { - // clear the toolbar - this._clearManipulatorBar(); - this.controlNodesActive = true; + exports._calculateSpringForces = function () { + var edgeLength, edge, edgeId; + var dx, dy, fx, fy, springForce, distance; + 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)) { + edgeLength = edge.customLength ? edge.length : this.constants.physics.springLength; + // this implies that the edges between big clusters are longer + edgeLength += (edge.to.clusterSize + edge.from.clusterSize - 2) * this.constants.clustering.edgeGrowth; - this.edgeBeingEdited = this._getSelectedEdge(); - this.edgeBeingEdited._enableControlNodes(); + dx = (edge.from.x - edge.to.x); + dy = (edge.from.y - edge.to.y); + distance = Math.sqrt(dx * dx + dy * dy); - this.manipulationDiv.innerHTML = "" + - "" + - "" + this.constants.labels['back'] + " " + - "
" + - "" + - "" + this.constants.labels['editEdgeDescription'] + ""; + if (distance == 0) { + distance = 0.01; + } - // bind the icon - var backButton = document.getElementById("network-manipulate-back"); - backButton.onclick = this._createManipulatorBar.bind(this); + // the 1/distance is so the fx and fy can be calculated without sine or cosine. + springForce = this.constants.physics.springConstant * (edgeLength - distance) / distance; - // 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; + fx = dx * springForce; + fy = dy * springForce; - // redraw to show the unselect - this._redraw(); + edge.from.fx += fx; + edge.from.fy += fy; + edge.to.fx -= fx; + edge.to.fy -= fy; + } + } + } + } }; - /** - * 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 function calculates the springforces on the nodes, accounting for the support nodes. * * @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._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; + + edgeLength = edge.customLength ? edge.length : this.constants.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._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. + * 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._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); + 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; } - this._redraw(); + + // 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._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(); + + /** + * 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); + + 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); + + 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"); + + 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"); + + 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"); + + 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; + } + + 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"; } - if (this.edgeBeingEdited.controlNodes.to.selected == true) { - this._editEdge(this.edgeBeingEdited.from.id, newNode.id); - this.edgeBeingEdited.controlNodes.to.unselect(); + else { + graph_toggleSmooth.style.background = "#FF8532"; } + + + switchConfigurations.apply(this); + + radioButton1.onchange = switchConfigurations.bind(this); + radioButton2.onchange = switchConfigurations.bind(this); + radioButton3.onchange = switchConfigurations.bind(this); } - else { - this.edgeBeingEdited._restoreControlNodes(); - } - this.freezeSimulation = false; - 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. + * This overwrites the this.constants. * + * @param constantsVariableName + * @param value * @private */ - 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(); - } - } + exports._overWriteGraphConstants = function (constantsVariableName, value) { + var nameArray = constantsVariableName.split("_"); + if (nameArray.length == 1) { + this.constants[nameArray[0]] = value; } - }; - - 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(); + 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; } }; /** - * Adds a node on the specified location + * this function is bound to the toggle smooth curves button. That is also why it is not in the prototype. */ - 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(); - } - } - }; + 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); + } /** - * connect two nodes with a new edge. + * this function is used to scramble the nodes * - * @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(); + 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.repositionNodes(); + } + this.moving = true; + this.start(); + } /** - * connect two nodes with a new edge. - * - * @private + * this is used to generate an options file from the playing with physics system. */ - 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(); - }); + 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 += ", " + } } - else { - alert(this.constants.labels["linkError"]); - this.moving = true; - this.start(); + 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 += '}}' } - else { - this.edgesData.update(defaultData); - this.moving = true; - this.start(); + if (optionsSpecific.length == 0) {options += "}"} + if (this.constants.smoothCurves != this.backupConstants.smoothCurves) { + options += ", smoothCurves: " + this.constants.smoothCurves; } + options += '};' } - }; - - /** - * Create the toolbar to edit the selected node. The label and the color can be changed. Other colors are derived from the chosen color. - * - * @private - */ - exports._editNode = function() { - if (this.triggerFunctions.edit && this.editMode == true) { - var node = this._getSelectedNode(); - var data = {id:node.id, - label: node.label, - group: node.group, - shape: node.shape, - color: { - background:node.color.background, - border:node.color.border, - highlight: { - background:node.color.highlight.background, - border:node.color.highlight.border + 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 += ", "; } - }}; - 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(); - }); + } + 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 { - alert(this.constants.labels["editError"]); + options += "enabled:true}"; } + options += '};' } - else { - alert(this.constants.labels["editBoundError"]); - } - }; - + this.optionsDiv.innerHTML = options; + } /** - * delete everything in the selection + * this is used to switch between barnesHut, repulsion and hierarchical. * - * @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(); - }); - } - else { - alert(this.constants.labels["deleteError"]) - } - } - else { - this.edgesData.remove(selectedEdges); - this.nodesData.remove(selectedNodes); - this._unselectAll(); - 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 { - alert(this.constants.labels["deleteClusterError"]); + } + 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(); } } - }; - - -/***/ }, -/* 59 */ -/***/ function(module, exports, __webpack_require__) { - - var util = __webpack_require__(1); - - exports._cleanNavigation = function() { - // clean up previous navigation items - var wrapper = document.getElementById('network-navigation_wrapper'); - if (wrapper != null) { - this.containerElement.removeChild(wrapper); + else { + this.constants.hierarchicalLayout.enabled = false; + this.constants.physics.hierarchicalRepulsion.enabled = false; + this.constants.physics.barnesHut.enabled = true; } - document.onmouseup = null; - }; + 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(); + } + /** - * 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. + * this generates the ranges depending on the iniital values. * - * @private + * @param id + * @param map + * @param constantsVariableName */ - 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']; - - 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); + function showValueOfRange (id,map,constantsVariableName) { + var valueId = id + "_value"; + var rangeValue = document.getElementById(id).value; - 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]]); - this.navigationDivs[navigationDivs[i]].onmousedown = this[navigationDivActions[i]].bind(this); + 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)); } - document.onmouseup = this._stopMovement.bind(this); - }; + if (constantsVariableName == "hierarchicalLayout_direction" || + constantsVariableName == "hierarchicalLayout_levelSeparation" || + constantsVariableName == "hierarchicalLayout_nodeSpacing") { + this._setupHierarchicalLayout(); + } + this.moving = true; + this.start(); + } - /** - * this stops all movement induced by the navigation buttons - * - * @private - */ - exports._stopMovement = function() { - this._xStopMoving(); - this._yStopMoving(); - this._stopZoom(); - }; +/***/ }, +/* 56 */ +/***/ function(module, exports, __webpack_require__) { - /** - * 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. - * - * @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 - util.preventDefault(event); - if (this.navigationDivs) { - this.navigationDivs['up'].className += " active"; - } + var map = {}; + function webpackContext(req) { + return __webpack_require__(webpackContextResolve(req)); }; - - - /** - * 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 - util.preventDefault(event); - if (this.navigationDivs) { - this.navigationDivs['down'].className += " active"; - } + 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; + +/***/ }, +/* 57 */ +/***/ function(module, exports, __webpack_require__) { /** - * move the screen left + * Calculate the forces the nodes apply on each other based on a repulsion field. + * This field is linearly approximated. + * * @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 - util.preventDefault(event); - if (this.navigationDivs) { - this.navigationDivs['left'].className += " active"; - } - }; + exports._calculateNodeForces = function () { + var dx, dy, angle, distance, fx, fy, combinedClusterSize, + repulsingForce, node1, node2, i, j; + var nodes = this.calculationNodes; + var nodeIndices = this.calculationNodeIndices; - /** - * 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 - util.preventDefault(event); - if (this.navigationDivs) { - this.navigationDivs['right'].className += " active"; - } - }; + // 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; - /** - * 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 - util.preventDefault(event); - if (this.navigationDivs) { - this.navigationDivs['zoomIn'].className += " active"; - } - }; + // 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 { + repulsingForce = a * distance + b; // linear approx of 1 / (1 + Math.exp((distance / minimumDistance - 1) * steepness)) + } - /** - * 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); - if (this.navigationDivs) { - this.navigationDivs['zoomOut'].className += " active"; - } - }; + // amplify the repulsion for clusters. + repulsingForce *= (combinedClusterSize == 0) ? 1 : 1 + combinedClusterSize * this.constants.clustering.forceAmplification; + repulsingForce = repulsingForce / distance; + fx = dx * repulsingForce; + fy = dy * repulsingForce; - /** - * Stop zooming and unhighlight the zoom controls - * @private - */ - exports._stopZoom = function() { - this.zoomIncrement = 0; - if (this.navigationDivs) { - this.navigationDivs['zoomIn'].className = this.navigationDivs['zoomIn'].className.replace(" active",""); - this.navigationDivs['zoomOut'].className = this.navigationDivs['zoomOut'].className.replace(" active",""); + node1.fx -= fx; + node1.fy -= fy; + node2.fx += fx; + node2.fy += fy; + } + } } }; +/***/ }, +/* 58 */ +/***/ function(module, exports, __webpack_require__) { + /** - * Stop moving in the Y direction and unHighlight the up and down + * Calculate the forces the nodes apply on eachother based on a repulsion field. + * This field is linearly approximated. + * * @private */ - exports._yStopMoving = function() { - this.yIncrement = 0; - if (this.navigationDivs) { - this.navigationDivs['up'].className = this.navigationDivs['up'].className.replace(" active",""); - this.navigationDivs['down'].className = this.navigationDivs['down'].className.replace(" active",""); - } - }; + 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; - /** - * Stop moving in the X direction and unHighlight left and right. - * @private - */ - exports._xStopMoving = function() { - this.xIncrement = 0; - if (this.navigationDivs) { - this.navigationDivs['left'].className = this.navigationDivs['left'].className.replace(" active",""); - this.navigationDivs['right'].className = this.navigationDivs['right'].className.replace(" active",""); - } - }; + // 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) { -/***/ }, -/* 60 */ -/***/ function(module, exports, __webpack_require__) { + dx = node2.x - node1.x; + dy = node2.y - node1.y; + distance = Math.sqrt(dx * dx + dy * dy); - 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; + + 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; } } } }; + /** - * 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 effects of the springs in the case of unsmooth curves. * * @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); - } + exports._calculateHierarchicalSpringForces = function () { + var edgeLength, edge, edgeId; + var dx, dy, fx, fy, springForce, distance; + var edges = this.edges; - 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; + var nodes = this.calculationNodes; + var nodeIndices = this.calculationNodeIndices; - 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; + + for (var i = 0; i < nodeIndices.length; i++) { + var node1 = nodes[nodeIndices[i]]; + node1.springFx = 0; + node1.springFy = 0; + } + + + // 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.customLength ? edge.length : this.constants.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; + + + + 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; + } } } } + } - // 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(); + // 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)); - // 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(); + node.fx += springFx; + node.fy += springFy; + } - // place the nodes on the canvas. This also stablilizes the system. - this._placeNodesByHierarchy(distribution); + // 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; - // start the simulation. - this.start(); - } + for (i = 0; i < nodeIndices.length; i++) { + var node = nodes[nodeIndices[i]]; + node.fx -= correctionFx; + node.fy -= correctionFy; } + }; +/***/ }, +/* 59 */ +/***/ function(module, exports, __webpack_require__) { /** - * This function places the nodes on the canvas based on the hierarchial distribution. + * 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. * - * @param {Object} distribution | obtained by the function this._getDistribution() * @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)) { + 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 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; + this._formBarnesHutTree(nodes,nodeIndices); - distribution[level].minPos += distribution[level].nodeSpacing; - } - } - else { - if (node.yFixed) { - node.y = distribution[level].minPos; - node.yFixed = false; + var barnesHutTree = this.barnesHutTree; - distribution[level].minPos += distribution[level].nodeSpacing; - } - } - this._placeBranchNodes(node.edges,node.id,distribution,node.level); - } - } + // place the nodes one by one recursively + for (var i = 0; i < nodeCount; i++) { + node = nodes[nodeIndices[i]]; + // 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); } } - - // stabilize the system after positioning. This function calls zoomExtent. - this._stabilize(); }; /** - * This function get the distribution of levels based on hubsize + * 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. * - * @returns {Object} + * @param parentBranch + * @param node * @private */ - exports._getDistribution = function() { - var distribution = {}; - var nodeId, node, level; + exports._getForceContribution = function(parentBranch,node) { + // we get no force contribution from an empty region + if (parentBranch.childrenCount > 0) { + var dx,dy,distance; - // 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; + // 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; } - else { - node.x = this.constants.hierarchicalLayout.levelSeparation*node.level; + var gravityForce = this.constants.physics.barnesHut.gravitationalConstant * parentBranch.mass * node.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); } - if (distribution[node.level] === undefined) { - distribution[node.level] = {amount: 0, nodes: {}, minPos:0, nodeSpacing:0}; + 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.mass / (distance * distance * distance); + var fx = dx * gravityForce; + var fy = dy * gravityForce; + node.fx += fx; + node.fy += fy; + } } - distribution[node.level].amount += 1; - distribution[node.level].nodes[nodeId] = node; } } + }; - // 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; - } - } + /** + * This function constructs the barnesHut tree recursively. It creates the root, splits it and starts placing the nodes. + * + * @param nodes + * @param nodeIndices + * @private + */ + exports._formBarnesHutTree = function(nodes,nodeIndices) { + var node; + var nodeCount = nodeIndices.length; + + 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 (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 - // 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); + + 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); + + // place the nodes one by one recursively + for (i = 0; i < nodeCount; i++) { + node = nodes[nodeIndices[i]]; + 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.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.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.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; - } - }; +/***/ }, +/* 60 */ +/***/ 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 87c2c38c..4801517d 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","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","equalArray","convert","type","Boolean","valueOf","isMoment","toDate","getType","toISOString","value","getAbsoluteLeft","elem","getBoundingClientRect","left","window","pageXOffset","getAbsoluteTop","top","pageYOffset","addClassName","className","classes","split","indexOf","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","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","Hammer","backgroundVertical","backgroundHorizontal","centerContainer","leftContainer","rightContainer","shadowTop","shadowBottom","shadowTopLeft","shadowBottomLeft","shadowTopRight","shadowBottomRight","_onTouch","_onPinch","_onDragStart","_onDrag","prevent_default","listeners","events","args","slice","scrollTop","scrollTopMin","touch","destroy","_stopAutoResize","component","_initAutoResize","setCustomTime","time","getCustomTime","newDataSet","initialLoad","fit","setWindow","getVisibleItems","setGroups","groups","what","dataRange","getItemRange","dataset","minItem","maxStartItem","maxEndItem","setSelection","getSelection","getWindow","getRange","resized","borderRootHeight","borderRootWidth","autoHeight","containerHeight","centerWidth","_updateScrollTop","visibilityTop","visibilityBottom","visibility","repaint","conversion","_startAutoResize","_onResize","lastWidth","lastHeight","watchTimer","setInterval","allowDragging","initialScrollTop","gesture","deltaY","oldScrollTop","_getScrollTop","newScrollTop","_setScrollTop","linegraph","backgroundHorizontalContainer","minimumStep","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","isMajor","now","hours","minutes","seconds","milliseconds","clone","direction","moveable","zoomable","zoomMin","zoomMax","_onDragEnd","_onHold","_onMouseWheel","validateDirection","getPointer","pageX","pageY","hammerUtil","changed","_applyRange","newStart","newEnd","deltaX","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","_isResized","_previousWidth","_previousHeight","showCurrentTime","parent","title","currentTimeTimer","showCustomTime","eventParams","drag","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","groupId","drawIcon","changeCalled","_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","visibleItems","byStart","byEnd","inner","foreground","marker","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","UNGROUPED","box","_updateUngrouped","_onSelectItem","_onMultiSelectItem","_onAddItem","addCallback","fn","Function","markDirty","unselect","select","rawVisibleItems","_deselect","_orderGroups","visibleInterval","zoomed","lastVisibleInterval","firstGroup","_firstGroup","firstMargin","nonFirstMargin","groupMargin","groupResized","firstGroupIndex","firstGroupId","ungrouped","getLabelSet","oldItemsData","getItems","_order","getGroups","itemData","_removeItem","groupData","groupOptions","oldGroupId","oldGroup","itemFromTarget","selected","dragLeftItem","dragRightItem","itemProps","groupFromTarget","changes","ctrlKey","srcEvent","shiftKey","oldSelection","newSelection","xAbs","newItem","itemSetFromTarget","side","iconSize","iconSpacing","textArea","drawLegendIcons","getComputedStyle","paddingTop","yAxisOrientation","defaultGroup","sampling","graphHeight","barChart","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","_drawPoints","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","stabilize","initializing","triggerFunctions","edit","editEdge","connect","del","constants","nodes","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","stabilizationIterations","link","editNode","back","addDescription","linkDescription","editEdgeDescription","addError","linkError","editError","editBoundError","deleteError","deleteClusterError","dragNetwork","dragNodes","hideEdgesOnDrag","hideNodesOnDrag","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","dragGraph","onEdit","onEditEdge","onConnect","onDelete","editMode","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","smooth","mass","internalMultiplier","parentEdgeId","positionBezierNode","mixin","storePosition","dataArray","allowedToMoveX","allowedToMoveY","focusOnNode","nodePosition","requiredScale","canvasCenter","distanceFromCenter","fromId","toId","widthSelected","customLength","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","borderWidthSelected","fx","fy","vx","vy","minForce","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","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","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__","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","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","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","total","_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","connectFromId","_createEdge","defaultData","finalizedData","sourceNodeId","targetNodeId","selectedNodes","selectedEdges","wrapper","navigationDivActions","_stopMovement","hubsize","definedLevel","undefinedLevel","_changeConstants","_determineLevels","distribution","_getDistribution","_placeNodesByHierarchy","minPos","_placeBranchNodes","amount","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","equalArray","convert","type","Boolean","valueOf","isMoment","toDate","getType","toISOString","value","getAbsoluteLeft","elem","getBoundingClientRect","left","window","pageXOffset","getAbsoluteTop","top","pageYOffset","addClassName","className","classes","split","indexOf","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","code","_initAutoResize","component","newDataSet","initialLoad","fit","setWindow","setGroups","groups","setSelection","getSelection","linegraph","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","groupId","drawIcon","backgroundHorizontal","changeCalled","_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","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","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","dataset","itemData","_removeItem","groupData","groupOptions","oldGroupId","oldGroup","itemFromTarget","selected","dragLeftItem","dragRightItem","itemProps","groupFromTarget","changes","ctrlKey","srcEvent","shiftKey","oldSelection","newSelection","xAbs","newItem","itemSetFromTarget","side","iconSize","iconSpacing","textArea","drawLegendIcons","getComputedStyle","paddingTop","yAxisOrientation","defaultGroup","sampling","graphHeight","barChart","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","_drawPoints","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","stabilize","initializing","triggerFunctions","edit","editEdge","connect","del","constants","nodes","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","stabilizationIterations","link","editNode","back","addDescription","linkDescription","editEdgeDescription","addError","linkError","editError","editBoundError","deleteError","deleteClusterError","dragNetwork","dragNodes","hideEdgesOnDrag","hideNodesOnDrag","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","dragGraph","onEdit","onEditEdge","onConnect","onDelete","editMode","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","smooth","mass","internalMultiplier","parentEdgeId","positionBezierNode","mixin","storePosition","dataArray","allowedToMoveX","allowedToMoveY","focusOnNode","nodePosition","requiredScale","canvasCenter","distanceFromCenter","fromId","toId","widthSelected","customLength","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","borderWidthSelected","fx","fy","vx","vy","minForce","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","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","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","args","listeners","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__","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","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","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","total","_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","connectFromId","_createEdge","defaultData","finalizedData","sourceNodeId","targetNodeId","selectedNodes","selectedEdges","wrapper","navigationDivActions","_stopMovement","hubsize","definedLevel","undefinedLevel","_changeConstants","_determineLevels","distribution","_getDistribution","_placeNodesByHierarchy","minPos","_placeBranchNodes","amount","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 5cf041a4..d27c229f 100644 --- a/dist/vis.min.js +++ b/dist/vis.min.js @@ -5,7 +5,7 @@ * A dynamic, browser-based visualization library. * * @version 3.1.1-SNAPSHOT - * @date 2014-07-22 + * @date 2014-07-23 * * @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(1),e.DOMutil=i(2),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(18),CurrentTime:i(19),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(40),e.hammer=i(41)},function(module,exports,__webpack_require__){var moment=__webpack_require__(40);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,m=p,g=u,f=Math.floor(.5*(u+p));if(0==u)f=-1;else if(1==u)r=l[f][i],f=r==e?0:-1;else{for(u-=1;0==c&&h>d;)n=l[Math.max(0,f-1)][i],r=l[f][i],a=l[Math.min(l.length-1,f+1)][i],r==e||e>n&&r>e||e>r&&a>e?(c=!0,r!=e&&("before"==s?e>n&&r>e&&(f=Math.max(0,f-1)):e>r&&a>e&&(f=Math.min(l.length-1,f+1)))):(e>r?m=Math.floor(.5*(u+p)):g=Math.floor(.5*(u+p)),o=Math.floor(.5*(u+p)),p==m&&u==g?(f=-1,c=!0):(u=g,p=m,f=Math.floor(.5*(u+p)))),d++;d>=h&&console.log("BinarySearch too many iterations. Aborting.")}return f}},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 m=h[p];c[m]=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={},m=0,g=l.length;g>m;m++){var f=l[m];u[f]=t.getValue(c,m)}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,m=i&&i.filter,g=[];if(void 0!=t)d=n._getItem(t,u),m&&!m(d)&&(d=null);else if(void 0!=e)for(c=0,p=e.length;p>c;c++)d=n._getItem(e[c],u),(!m||m(d))&&g.push(d);else for(l in this._data)this._data.hasOwnProperty(l)&&(d=n._getItem(l,u),(!m||m(d))&&g.push(d));if(i&&i.order&&void 0==t&&this._sort(g,i.order),i&&i.fields){var f=i.fields;if(void 0!=t)d=this._filterFields(d,f);else for(c=0,p=g.length;p>c;c++)g[c]=this._filterFields(g[c],f)}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(g[c]);return s}return g},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(45),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 g=(t-p)/(m-p),f=240*g,v=this._hsv2rgb(f,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?(f.textAlign="center",f.textBaseline="top",o.y+=b):Math.sin(2*_)<0?(f.textAlign="right",f.textBaseline="middle"):(f.textAlign="left",f.textBaseline="middle"),f.fillStyle=this.colorAxis,f.fillText(" "+i.getCurrent()+" ",o.x,o.y),i.next()}for(f.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?(f.textAlign="center",f.textBaseline="top",o.y+=b):Math.sin(2*_)>0?(f.textAlign="right",f.textBaseline="middle"):(f.textAlign="left",f.textBaseline="middle"),f.fillStyle=this.colorAxis,f.fillText(" "+i.getCurrent()+" ",o.x,o.y),i.next();for(f.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())),f.strokeStyle=this.colorAxis,f.beginPath(),f.moveTo(t.x,t.y),f.lineTo(t.x-b,t.y),f.stroke(),f.textAlign="right",f.textBaseline="middle",f.fillStyle=this.colorAxis,f.fillText(i.getCurrent()+" ",t.x-5,t.y),i.next();f.lineWidth=1,t=this._convert3Dto2D(new h(n,r,this.zMin)),e=this._convert3Dto2D(new h(n,r,this.zMax)),f.strokeStyle=this.colorAxis,f.beginPath(),f.moveTo(t.x,t.y),f.lineTo(e.x,e.y),f.stroke(),f.lineWidth=1,p=this._convert3Dto2D(new h(this.xMin,this.yMin,this.zMin)),m=this._convert3Dto2D(new h(this.xMax,this.yMin,this.zMin)),f.strokeStyle=this.colorAxis,f.beginPath(),f.moveTo(p.x,p.y),f.lineTo(m.x,m.y),f.stroke(),p=this._convert3Dto2D(new h(this.xMin,this.yMax,this.zMin)),m=this._convert3Dto2D(new h(this.xMax,this.yMax,this.zMin)),f.strokeStyle=this.colorAxis,f.beginPath(),f.moveTo(p.x,p.y),f.lineTo(m.x,m.y),f.stroke(),f.lineWidth=1,t=this._convert3Dto2D(new h(this.xMin,this.yMin,this.zMin)),e=this._convert3Dto2D(new h(this.xMin,this.yMax,this.zMin)),f.strokeStyle=this.colorAxis,f.beginPath(),f.moveTo(t.x,t.y),f.lineTo(e.x,e.y),f.stroke(),t=this._convert3Dto2D(new h(this.xMax,this.yMin,this.zMin)),e=this._convert3Dto2D(new h(this.xMax,this.yMax,this.zMin)),f.strokeStyle=this.colorAxis,f.beginPath(),f.moveTo(t.x,t.y),f.lineTo(e.x,e.y),f.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?(f.textAlign="center",f.textBaseline="top"):Math.sin(2*_)<0?(f.textAlign="right",f.textBaseline="middle"):(f.textAlign="left",f.textBaseline="middle"),f.fillStyle=this.colorAxis,f.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?(f.textAlign="center",f.textBaseline="top"):Math.sin(2*_)>0?(f.textAlign="right",f.textBaseline="middle"):(f.textAlign="left",f.textBaseline="middle"),f.fillStyle=this.colorAxis,f.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)),f.textAlign="right",f.textBaseline="middle",f.fillStyle=this.colorAxis,f.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,m,g=this.frame.canvas,f=g.getContext("2d");if(!(void 0===this.dataPoints||this.dataPoints.length<=0)){for(n=0;n0}else r=!0;r?(m=(t.point.z+e.point.z+i.point.z+o.point.z)/4,c=240*(1-(m-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,f.lineWidth=l,f.fillStyle=a,f.strokeStyle=d,f.beginPath(),f.moveTo(t.screen.x,t.screen.y),f.lineTo(e.screen.x,e.screen.y),f.lineTo(o.screen.x,o.screen.y),f.lineTo(i.screen.x,i.screen.y),f.closePath(),f.fill(),f.stroke()}}else for(n=0;np&&(p=0);var u,m,g;this.style===s.STYLE.DOTCOLOR?(u=240*(1-(d.point.value-this.valueMin)*this.scale.value),m=this._hsv2rgb(u,1,1),g=this._hsv2rgb(u,1,.8)):this.style===s.STYLE.DOTSIZE?(m=this.colorDot,g=this.colorDotBorder):(u=240*(1-(d.point.z-this.zMin)*this.scale.z/this.verticalRatio),m=this._hsv2rgb(u,1,1),g=this._hsv2rgb(u,1,.8)),i.lineWidth=1,i.strokeStyle=g,i.fillStyle=m,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,m=[u[0].screen,u[1].screen,u[2].screen],g=[u[2].screen,u[3].screen,u[0].screen];if(this._insideTriangle(h,m)||this._insideTriangle(h,g))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){if(!(this instanceof s))throw new SyntaxError("Constructor must be called with the new operator");var o=this;this.defaultOptions={start:null,end:null,autoResize:!0,orientation:"bottom",width:null,height:null,maxHeight:null,minHeight:null},this.options=r.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:o._toScreen.bind(o),toGlobalScreen:o._toGlobalScreen.bind(o),toTime:o._toTime.bind(o),toGlobalTime:o._toGlobalTime.bind(o)}},this.range=new d(this.body),this.components.push(this.range),this.body.range=this.range,this.timeAxis=new l(this.body),this.components.push(this.timeAxis),this.body.util.snap=this.timeAxis.snap.bind(this.timeAxis),this.currentTime=new c(this.body),this.components.push(this.currentTime),this.customTime=new p(this.body),this.components.push(this.customTime),this.itemSet=new u(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(45),n=i(41),r=i(1),a=i(3),h=i(4),d=i(15),l=i(27),c=i(19),p=i(20),u=i(24);o(s.prototype),s.prototype._create=function(t){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)),this.hammer=n(this.dom.root,{prevent_default:!0}),this.listeners={};var e=this,i=["touch","pinch","tap","doubletap","hold","dragstart","drag","dragend","mousewheel","DOMMouseScroll"];if(i.forEach(function(t){var i=function(){var i=[t].concat(Array.prototype.slice.call(arguments,0));e.emit.apply(e,i)};e.hammer.on(t,i),e.listeners[t]=i}),this.props={root:{},background:{},centerContainer:{},leftContainer:{},rightContainer:{},center:{},left:{},right:{},top:{},bottom:{},border:{},scrollTop:0,scrollTopMin:0},this.touch={},!t)throw new Error("No container provided");t.appendChild(this.dom.root)},s.prototype.destroy=function(){this.clear(),this.off(),this._stopAutoResize(),this.dom.root.parentNode&&this.dom.root.parentNode.removeChild(this.dom.root),this.dom=null;for(var t in this.listeners)this.listeners.hasOwnProperty(t)&&delete this.listeners[t];this.listeners=null,this.hammer=null,this.components.forEach(function(t){t.destroy()}),this.body=null},s.prototype.setOptions=function(t){if(t){var e=["width","height","minHeight","maxHeight","autoResize","start","end","orientation"];r.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.setCustomTime=function(t){if(!this.customTime)throw new Error("Cannot get custom time: Custom time bar is not enabled");this.customTime.setCustomTime(t)},s.prototype.getCustomTime=function(){if(!this.customTime)throw new Error("Cannot get custom time: Custom time bar is not enabled");return this.customTime.getCustomTime()},s.prototype.setItems=function(t){var e,i=null==this.itemsData;if(e=t?t instanceof a||t instanceof h?t:new a(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?r.convert(this.options.start,"Date"):null,o="end"in this.options?r.convert(this.options.end,"Date"):null;this.setWindow(s,o)}},s.prototype.getVisibleItems=function(){return this.itemSet&&this.itemSet.getVisibleItems()||[]},s.prototype.setGroups=function(t){var e;e=t?t instanceof a||t instanceof h?t:new a(t):null,this.groupsData=e,this.itemSet.setGroups(e)},s.prototype.clear=function(t){(!t||t.items)&&this.setItems(null),(!t||t.groups)&&this.setGroups(null),(!t||t.options)&&(this.components.forEach(function(t){t.setOptions(t.defaultOptions)}),this.setOptions(this.defaultOptions))},s.prototype.fit=function(){var t=this.getItemRange(),e=t.min,i=t.max;if(null!=e&&null!=i){var s=i.valueOf()-e.valueOf();0>=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.getItemRange=function(){var t=this.itemsData.getDataSet(),e=null,i=null;if(t){var s=t.min("start");e=s?r.convert(s.start,"Date").valueOf():null;var o=t.max("start");o&&(i=r.convert(o.start,"Date").valueOf());var n=t.max("end");n&&(i=null==i?r.convert(n.end,"Date").valueOf():Math.max(i,r.convert(n.end,"Date").valueOf()))}return{min:null!=e?new Date(e):null,max:null!=i?new Date(i):null}},s.prototype.setSelection=function(t){this.itemSet&&this.itemSet.setSelection(t)},s.prototype.getSelection=function(){return this.itemSet&&this.itemSet.getSelection()||[]},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.scrollTop=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.getItemRange=function(){var t=this.itemsData,e=null,i=null;if(t){var s=t.min("start");e=s?r.convert(s.start,"Date").valueOf():null;var o=t.max("start");o&&(i=r.convert(o.start,"Date").valueOf());var n=t.max("end");n&&(i=null==i?r.convert(n.end,"Date").valueOf():Math.max(i,r.convert(n.end,"Date").valueOf()))}return{min:null!=e?new Date(e):null,max:null!=i?new Date(i):null}},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.backgroundHorizontalContainer.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.backgroundHorizontalContainer.style.width=i.background.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.backgroundHorizontalContainer.style.left="0",s.backgroundHorizontalContainer.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.backgroundHorizontal.style.left="0",s.backgroundHorizontal.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._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.scrollTopn&&(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(42),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)&&(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;if(0==this.amountOfGroups)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 e=this.props,i=this.dom.frame;i.className="dataaxis",this._calculateCharSize();var s=this.options.orientation,o=this.options.showMinorLabels,n=this.options.showMajorLabels;e.minorLabelHeight=o?e.minorCharHeight:0,e.majorLabelHeight=n?e.majorCharHeight:0,e.minorLineWidth=this.body.dom.backgroundHorizontal.offsetWidth-this.lineOffset-this.width+2*this.options.minorLinesOffset,e.minorLineHeight=1,e.majorLineWidth=this.body.dom.backgroundHorizontal.offsetWidth-this.lineOffset-this.width+2*this.options.majorLinesOffset,e.majorLineHeight=1,"left"==s?(i.style.top="0",i.style.left="0",i.style.bottom="",i.style.width=this.width+"px",i.style.height=this.height+"px"):(i.style.top="",i.style.bottom="0",i.style.left="0",i.style.width=this.width+"px",i.style.height=this.height+"px"),t=this._redrawLabels(),1==this.options.icons&&this._redrawGroupIcons()}return t},s.prototype._redrawLabels=function(){n.prepareElements(this.DOMelements);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),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),this.redraw(),!0):(n.cleanupElements(this.DOMelements),!1)},s.prototype._redrawLabel=function(t,e,i,s,o){var r=n.getDOMElement("div",this.DOMelements,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,m=this.visibleItems.length;m>u;u++){var g=this.visibleItems[u];g.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),t instanceof r&&-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=n.option.asSize,s=this.options,o=s.orientation,r=!1,a=this.dom.frame,h=s.editable.updateTime||s.editable.updateGroup;a.className="itemset"+(h?" editable":""),r=this._orderGroups()||r;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},m={item:t.item,axis:t.item.vertical/2},g=0,f=t.axis+t.item.vertical;return n.forEach(this.groups,function(t){var i=t==p?u:m,s=t.redraw(e,i,c);r=s||r,g+=t.height}),g=Math.max(g,f),this.stackDirty=!1,a.style.height=i(g),this.props.top=a.offsetTop,this.props.left=a.offsetLeft,this.props.width=a.offsetWidth,this.props.height=g,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",r=this._isResized()||r},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[u];return i||null},s.prototype._updateUngrouped=function(){var t=this.groups[u];if(this.groupsData)t&&(t.hide(),delete this.groups[u]);else if(!t){var e=null,i=null;t=new d(e,i,this),this.groups[u]=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 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&&(n.forEach(this.itemListeners,function(t,e){s.off(e,t)}),e=s.getIds(),this._onRemove(e)),this.itemsData){var o=this.id;n.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&&(n.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;n.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(){n.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==u)throw new Error("Illegal group id. "+t+" is a reserved id.");var o=Object.create(e.options);n.extend(o,{height:null}),s=new d(t,i,e),e.groups[t]=s;for(var r in e.items)if(e.items.hasOwnProperty(r)){var a=e.items[r];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=!n.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:u,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:u,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:u,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 r=e.itemsData.get(o.id);this.options.onUpdate(r,function(t){t&&e.itemsData.update(t)})}else{var a=n.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]=n.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(){if(0==this.options[this.side].visible||0==this.amountOfGroups||0==this.options.enabled)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 t="";for(var e in this.groups)this.groups.hasOwnProperty(e)&&(t+=this.groups[e].content+"
");this.dom.textArea.innerHTML=t,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)&&(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,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(f);break}e.push(f)}}else for(var g=0;gp&&f.x0){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?(1==r&&(this.yAxisLeft.lineOffset=this.yAxisRight.width),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){var i,s=.1*e.options.barChart.width,o=0,r=e.options.barChart.width;"left"==e.options.barChart.align?o-=.5*r:"right"==e.options.barChart.align&&(o+=.5*r);for(var a=0;a0&&(i=Math.min(i,Math.abs(t[a-1].x-t[a].x))),r>i&&(r=s>i?s:i),n.drawBar(t[a].x+o,t[a].y,r,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._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,m,g,f,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)),f=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*f*v+b,m=3*x*(x+v),m>0&&(m=1/m),g=3*f*(f+v),g>0&&(g=1/g),a={x:(-b*s.x+p*o.x+_*n.x)*m,y:(-b*s.y+p*o.y+_*n.y)*m},h={x:(y*o.x+u*n.x-b*r.x)*g,y:(y*o.y+u*n.y-b*r.y)*g},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),m=n.getLabelMajor(u),g=m.length*(this.props.majorCharWidth||10)+10;(void 0==h||h>g)&&this._repaintMajorText(0,m,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.width="100%",this.height="100%",this.renderRefreshRate=60,this.renderTimestep=1e3/this.renderRefreshRate,this.renderTime=.5*this.renderTimestep,this.maxPhysicsTicksPerRender=3,this.physicsDiscreteStepsize=.5,this.stabilize=!0,this.selectable=!0,this.initializing=!0,this.triggerFunctions={add:null,edit:null,editEdge:null,connect:null,del:null},this.constants={nodes:{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,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},this.hoverObj={nodes:{},edges:{}},this.controlNodesActive=!1;var o=this;this.groups=new u,this.images=new m,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.stabilize&&this.zoomExtent(!0,this.constants.clustering.enabled),this.constants.clustering.enabled&&this.startWithClustering()}var o=i(45),n=i(41),r=i(46),a=i(1),h=i(42),d=i(3),l=i(4),c=i(38),p=i(39),u=i(34),m=i(35),g=i(36),f=i(33),v=i(37),y=i(44);i(43),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.stabilize){var o=this;setTimeout(function(){o._stabilize(),o.start()},0)}else this.start()},s.prototype.setOptions=function(t){if(t){var e;if(void 0!==t.width&&(this.width=t.width),void 0!==t.height&&(this.height=t.height),void 0!==t.stabilize&&(this.stabilize=t.stabilize),void 0!==t.selectable&&(this.selectable=t.selectable),void 0!==t.freezeForStabilization&&(this.constants.freezeForStabilization=t.freezeForStabilization),void 0!==t.configurePhysics&&(this.constants.configurePhysics=t.configurePhysics),void 0!==t.stabilizationIterations&&(this.constants.stabilizationIterations=t.stabilizationIterations),void 0!==t.dragNetwork&&(this.constants.dragNetwork=t.dragNetwork),void 0!==t.dragNodes&&(this.constants.dragNodes=t.dragNodes),void 0!==t.zoomable&&(this.constants.zoomable=t.zoomable),void 0!==t.hover&&(this.constants.hover=t.hover),void 0!==t.hideEdgesOnDrag&&(this.constants.hideEdgesOnDrag=t.hideEdgesOnDrag),void 0!==t.hideNodesOnDrag&&(this.constants.hideNodesOnDrag=t.hideNodesOnDrag),void 0!==t.dragGraph)throw new Error("Option dragGraph is renamed to dragNetwork");if(void 0!==t.labels)for(e in t.labels)t.labels.hasOwnProperty(e)&&(this.constants.labels[e]=t.labels[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),t.physics){if(t.physics.barnesHut){this.constants.physics.barnesHut.enabled=!0;for(e in t.physics.barnesHut)t.physics.barnesHut.hasOwnProperty(e)&&(this.constants.physics.barnesHut[e]=t.physics.barnesHut[e])}if(t.physics.repulsion){this.constants.physics.barnesHut.enabled=!1;for(e in t.physics.repulsion)t.physics.repulsion.hasOwnProperty(e)&&(this.constants.physics.repulsion[e]=t.physics.repulsion[e])}if(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(void 0!==t.smoothCurves)if("boolean"==typeof t.smoothCurves)this.constants.smoothCurves.enabled=t.smoothCurves;else{this.constants.smoothCurves.enabled=!0;for(e in t.smoothCurves)t.smoothCurves.hasOwnProperty(e)&&(this.constants.smoothCurves[e]=t.smoothCurves[e])}if(t.hierarchicalLayout){this.constants.hierarchicalLayout.enabled=!0;for(e in t.hierarchicalLayout)t.hierarchicalLayout.hasOwnProperty(e)&&(this.constants.hierarchicalLayout[e]=t.hierarchicalLayout[e])}else void 0!==t.hierarchicalLayout&&(this.constants.hierarchicalLayout.enabled=!1);if(t.clustering){this.constants.clustering.enabled=!0;for(e in t.clustering)t.clustering.hasOwnProperty(e)&&(this.constants.clustering[e]=t.clustering[e])}else void 0!==t.clustering&&(this.constants.clustering.enabled=!1);if(t.navigation){this.constants.navigation.enabled=!0;for(e in t.navigation)t.navigation.hasOwnProperty(e)&&(this.constants.navigation[e]=t.navigation[e])}else void 0!==t.navigation&&(this.constants.navigation.enabled=!1);if(t.keyboard){this.constants.keyboard.enabled=!0;for(e in t.keyboard)t.keyboard.hasOwnProperty(e)&&(this.constants.keyboard[e]=t.keyboard[e])}else void 0!==t.keyboard&&(this.constants.keyboard.enabled=!1);if(t.dataManipulation){this.constants.dataManipulation.enabled=!0;for(e in t.dataManipulation)t.dataManipulation.hasOwnProperty(e)&&(this.constants.dataManipulation[e]=t.dataManipulation[e]);this.editMode=this.constants.dataManipulation.initiallyVisible}else void 0!==t.dataManipulation&&(this.constants.dataManipulation.enabled=!1);if(t.edges){for(e in t.edges)t.edges.hasOwnProperty(e)&&"object"!=typeof t.edges[e]&&(this.constants.edges[e]=t.edges[e]);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.edges.dash&&(void 0!==t.edges.dash.length&&(this.constants.edges.dash.length=t.edges.dash.length),void 0!==t.edges.dash.gap&&(this.constants.edges.dash.gap=t.edges.dash.gap),void 0!==t.edges.dash.altLength&&(this.constants.edges.dash.altLength=t.edges.dash.altLength)) -}if(t.nodes){for(e in t.nodes)t.nodes.hasOwnProperty(e)&&(this.constants.nodes[e]=t.nodes[e]);t.nodes.color&&(this.constants.nodes.color=a.parseColor(t.nodes.color))}if(t.groups)for(var i in t.groups)if(t.groups.hasOwnProperty(i)){var s=t.groups[i];this.groups.add(i,s)}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.width,this.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 g&&r.id!=a||r instanceof f||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 g(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 g(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 f(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 f(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.width,this.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.color;return"to"==this.inheritColor?t={highlight:this.to.color.highlight.border,hover:this.to.color.hover.border,color:this.to.color.border}:("from"==this.inheritColor||1==this.inheritColor)&&(t={highlight:this.from.color.highlight.border,hover:this.from.color.hover.border,color:this.from.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.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.length/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.widthMax)*this.networkScaleInv:1==this.hover?Math.min(this.hoverWidth,this.widthMax)*this.networkScaleInv:this.width*this.networkScaleInv},s.prototype._getViaCoordinates=function(){var t=null,e=null,i=this.smoothCurves.roundness,s=this.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.width)*this.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.color.highlight,t.fillStyle=this.color.highlight):1==this.hover?(t.strokeStyle=this.color.hover,t.fillStyle=this.color.hover):(t.strokeStyle=this.color.color,t.fillStyle=this.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.smoothCurves.dynamic&&1==this.smoothCurves.enabled?s=this.via:1==this.smoothCurves.enabled&&(s=this._getViaCoordinates()),1==this.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),m=(r-u)/r;if(1==this.smoothCurves.enabled&&null!=s.x?(c=(1-m)*s.x+m*this.to.x,p=(1-m)*s.y+m*this.to.y):(c=(1-m)*this.from.x+m*this.to.x,p=(1-m)*this.from.y+m*this.to.y),t.beginPath(),t.moveTo(d,l),1==this.smoothCurves.enabled&&null!=s.x?t.quadraticCurveTo(s.x,s.y,c,p):t.lineTo(c,p),t.stroke(),i=(10+5*this.width)*this.arrowScaleFactor,t.arrow(c,p,e,i),t.fill(),t.stroke(),this.label){var g;if(1==this.smoothCurves.enabled&&null!=s){var f=.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));g={x:f,y:v}}else g=this._pointOnLine(.5);this._label(t,this.label,g.x,g.y)}}else{var y,b,_,x=this.from,w=.25*Math.max(100,this.length);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.width)*this.arrowScaleFactor;t.arrow(_.x,_.y,_.angle,i),t.fill(),t.stroke(),this.label&&(g=this._pointOnCircle(y,b,w,.5),this._label(t,this.label,g.x,g.y))}},s.prototype._getDistanceToEdge=function(t,e,i,s,o,n){if(this.from!=this.to){if(1==this.smoothCurves.enabled){var r,a;if(1==this.smoothCurves.enabled&&1==this.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,m,g,f=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(m,g,p,u,o,n),f=f>d?d:f),m=p,g=u;return f}return this._getDistanceToLine(t,e,i,s,o,n)}var p,u,v,y,b=this.length/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&&(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.smoothCurves.dynamic&&1==this.smoothCurves.enabled?e=this.via:1==this.smoothCurves.enabled&&(e=this._getViaCoordinates()),1==this.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.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){this.selected=!1,this.hover=!1,this.edges=[],this.dynamicEdges=[],this.reroutedEdges={},this.group=s.nodes.group,this.fontSize=Number(s.nodes.fontSize),this.fontFace=s.nodes.fontFace,this.fontColor=s.nodes.fontColor,this.fontDrawThreshold=3,this.color=s.nodes.color,this.id=void 0,this.shape=s.nodes.shape,this.image=s.nodes.image,this.x=null,this.y=null,this.xFixed=!1,this.yFixed=!1,this.horizontalAlignLeft=!0,this.verticalAlignTop=!0,this.radius=s.nodes.radius,this.baseRadiusValue=s.nodes.radius,this.radiusFixed=!1,this.radiusMin=s.nodes.radiusMin,this.radiusMax=s.nodes.radiusMax,this.level=-1,this.preassignedLevel=!1,this.borderWidth=s.nodes.borderWidth,this.borderWidthSelected=s.nodes.borderWidthSelected,this.imagelist=e,this.grouplist=i,this.fx=0,this.fy=0,this.vx=0,this.vy=0,this.minForce=s.minForce,this.damping=s.physics.damping,this.mass=1,this.fixedData={x:null,y:null},this.setProperties(t,s),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){if(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.group&&(this.group=t.group),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.borderWidth&&(this.borderWidth=t.borderWidth),void 0!==t.borderWidthSelected&&(this.borderWidthSelected=t.borderWidthSelected),void 0!==t.mass&&(this.mass=t.mass),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(void 0!==this.group&&""!=this.group){var i=this.grouplist.get(this.group);for(var s in i)i.hasOwnProperty(s)&&(this[s]=i[s])}if(void 0!==t.shape&&(this.shape=t.shape),void 0!==t.image&&(this.image=t.image),void 0!==t.radius&&(this.radius=t.radius,this.baseRadiusValue=this.radius),void 0!==t.color&&(this.color=o.parseColor(t.color)),void 0!==t.fontColor&&(this.fontColor=t.fontColor),void 0!==t.fontSize&&(this.fontSize=t.fontSize),void 0!==t.fontFace&&(this.fontFace=t.fontFace),void 0!==this.image&&""!=this.image){if(!this.imagelist)throw"No imagelist provided";this.imageObj=this.imagelist.load(this.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.shape&&(this.radiusMin=e.nodes.widthMin,this.radiusMax=e.nodes.widthMax),this.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.shape){case"circle":case"dot":return this.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.mass;this.vx+=i*t,this.x+=this.vx*t}if(!this.yFixed){var s=this.damping*this.vy,o=(this.fy-s)/this.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.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.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.radius=(this.radiusMin+this.radiusMax)/2;else{var i=(this.radiusMax-this.radiusMin)/(e-t);this.radius=(this.value-t)*i+this.radiusMin}this.baseRadiusValue=this.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.radius=this.baseRadiusValue;var i=this.imageObj.height/this.imageObj.width;void 0!==i?(t=this.radius||this.imageObj.width,e=this.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.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.borderWidth,s=this.borderWidthSelected||2*this.borderWidth;t.strokeStyle=this.selected?this.color.highlight.border:this.hover?this.color.hover.border:this.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.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.color.highlight.background:this.color.background,t.roundRect(this.left,this.top,this.width,this.height,this.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.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.borderWidth,s=this.borderWidthSelected||2*this.borderWidth;t.strokeStyle=this.selected?this.color.highlight.border:this.hover?this.color.hover.border:this.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.color.highlight.background:this.hover?this.color.hover.background:this.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.radius=s/2,this.width=s,this.height=s,this.radius+=.5*Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeRadiusFactor,this.growthIndicator=this.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.borderWidth,s=this.borderWidthSelected||2*this.borderWidth;t.strokeStyle=this.selected?this.color.highlight.border:this.hover?this.color.hover.border:this.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.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.color.highlight.background:this.hover?this.color.hover.background:this.color.background,t.circle(this.x,this.y,this.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.color.highlight.background:this.hover?this.color.hover.background:this.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.radius=this.baseRadiusValue;var t=2*this.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.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.borderWidth,o=this.borderWidthSelected||2*this.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.color.highlight.border:this.hover?this.color.hover.border:this.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.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.color.highlight.background:this.hover?this.color.hover.background:this.color.background,t[e](this.x,this.y,this.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.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&&this.fontSize*this.networkScale>this.fontDrawThreshold){t.font=(this.selected?"bold ":"")+this.fontSize+"px "+this.fontFace,t.fillStyle=this.fontColor||"black",t.textAlign=o||"center",t.textBaseline=n||"middle";var a=e.split("\n"),h=a.length,d=this.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.fontSize+"px "+this.fontFace;for(var e=this.label.split("\n"),i=(this.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,O="";" "==L||" "==L||"\n"==L||"\r"==L;)o();do{var t=!1;if("#"==L){for(var e=T-1;" "==D.charAt(e)||" "==D.charAt(e);)e--;if("\n"==D.charAt(e)||""==D.charAt(e)){for(;""!=L&&"\n"!=L;)o();t=!0}}if("/"==L&&"/"==n()){for(;""!=L&&"\n"!=L;)o();t=!0}if("/"==L&&"*"==n()){for(;""!=L;){if("*"==L&&"/"==n()){o(),o();break}o()}t=!0}for(;" "==L||" "==L||"\n"==L||"\r"==L;)o()}while(t);if(""==L)return void(k=C.DELIMITER);var i=L+n();if(E[i])return k=C.DELIMITER,O=i,o(),void o();if(E[L])return k=C.DELIMITER,O=L,void o();if(r(L)||"-"==L){for(O+=L,o();r(L);)O+=L,o();return"false"==O?O=!1:"true"==O?O=!0:isNaN(Number(O))||(O=Number(O)),void(k=C.IDENTIFIER)}if('"'==L){for(o();""!=L&&('"'!=L||'"'==L&&'"'==n());)O+=L,'"'==L&&o(),o();if('"'!=L)throw x('End of string " expected');return o(),void(k=C.IDENTIFIER)}for(k=C.UNKNOWN;""!=L;)O+=L,o();throw new SyntaxError('Syntax error in part "'+w(O,30)+'"')}function u(){var t={};if(s(),p(),"strict"==O&&(t.strict=!0,p()),("graph"==O||"digraph"==O)&&(t.type=O,p()),k==C.IDENTIFIER&&(t.id=O,p()),"{"!=O)throw x("Angle bracket { expected");if(p(),m(t),"}"!=O)throw x("Angle bracket } expected");if(p(),""!==O)throw x("End of file expected");return p(),delete t.node,delete t.edge,delete t.graph,t}function m(t){for(;""!==O&&"}"!=O;)g(t),";"==O&&p()}function g(t){var e=f(t);if(e)return void b(t,e);var i=v(t);if(!i){if(k!=C.IDENTIFIER)throw x("Identifier expected");var s=O;if(p(),"="==O){if(p(),k!=C.IDENTIFIER)throw x("Identifier expected");t[s]=O,p()}else y(t,s)}}function f(t){var e=null;if("subgraph"==O&&(e={},e.type="subgraph",p(),k==C.IDENTIFIER&&(e.id=O,p())),"{"==O){if(p(),e||(e={}),e.parent=t,e.node=t.node,e.edge=t.edge,e.graph=t.graph,m(e),"}"!=O)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"==O?(p(),t.node=_(),"node"):"edge"==O?(p(),t.edge=_(),"edge"):"graph"==O?(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(;"->"==O||"--"==O;){var i,s=O;p();var o=f(t);if(o)i=o;else{if(k!=C.IDENTIFIER)throw x("Identifier or subgraph expected");i=O,d(t,{id:i}),p()}var n=_(),r=c(t,e,i,s,n);l(t,r),e=i}}function _(){for(var t=null;"["==O;){for(p(),t={};""!==O&&"]"!=O;){if(k!=C.IDENTIFIER)throw x("Attribute name expected");var e=O;if(p(),"="!=O)throw x("Equal sign = expected");if(p(),k!=C.IDENTIFIER)throw x("Attribute value expected");var i=O;h(t,e,i),p(),","==O&&p()}if("]"!=O)throw x("Bracket ] expected");p()}return t}function x(t){return new SyntaxError(t+', got "'+w(O,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,L="",O="",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;rs;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,m=e+(s-r/2),g=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,m),this.bezierCurveTo(l,m+d,p+h,g,p,g),this.bezierCurveTo(p-h,g,t,m+d,t,m),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(55),o=i(49),n=i(50),r=i(51),a=i(52),h=i(53),d=i(54);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 m(t,e,i){return i||(i=u()[t]?"keydown":"keypress"),"keypress"==i&&e.length&&(i="keydown"),i}function g(t,e,s,o){E[t]=0,o||(o=m(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 g(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,L=1;20>L;++L)_[111+L]="f"+L;for(L=0;9>=L;++L)_[L+96]=L;e(document,"keypress",l),e(document,"keydown",l),e(document,"keyup",l);var O={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=O},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 m(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){O(t),m(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 m(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 g(t){var e,i={};for(e in t)t.hasOwnProperty(e)&&ke.hasOwnProperty(e)&&(i[e]=t[e]);return i}function f(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 L(t)?366:365}function L(t){return t%4===0&&t%100!==0||t%400===0}function O(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[Le]<0||t._a[Le]>999?Le:-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,Oe[t]||(Oe[t]=new c),Oe[t].set(e),Oe[t]}function z(t){delete Oe[t]}function P(t){var e,s,o,n,r=0,a=function(t){if(!Oe[t]&&Ne)try{i(56)("./"+t)}catch(e){}return Oe[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[Le]=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),O(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));m(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=g(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),m(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[Le])*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"):Oe[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?m(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)},m(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 m({},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:f(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 L(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,m(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=f(o/1e3),a.seconds=t%60,e=f(t/60),a.minutes=e%60,i=f(e/60),a.hours=i%24,n+=f(i/24),a.days=n%30,r+=f(n/30),a.months=r%12,s=f(r/12),a.years=s},weeks:function(){return f(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)&&(ge(be,ni[be]),me(be.toLowerCase()));ge("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)),fe(!0))}).call(this)}).call(e,function(){return this}(),i(60)(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",m=a.POINTER_TOUCH="touch",g=a.POINTER_PEN="pen",f=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[f]=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=m;return x.inStr(s.type,"mouse")||S.matchType(u,s)?o=u:S.matchType(g,s)&&(o=g),{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[m]=i===(e.MSPOINTER_TYPE_TOUCH||m),s[g]=i===(e.MSPOINTER_TYPE_PEN||g),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,f,function(t){i.enabled&&t.eventType==f?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[f],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 f: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 f: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 f: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){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.mass>n.from.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.mass>e.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.group,shape:t.shape,color:{background:t.color.background,border:t.color.border,highlight:{background:t.color.highlight.background,border:t.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);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=0;i0){"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,m=4/3,g=this.constants.physics.repulsion.nodeDistance,f=g;for(d=0;di&&(r=.5*f>i?1:v*i+m,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]],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.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.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;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)),m=.5*u,g=.5*(o+r),f=.5*(n+a),v={root:{centerOfMass:{x:0,y:0},mass:0,range:{minX:g-m,maxX:g+m,minY:f-m,maxY:f+m},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]],this._placeInTree(v.root,i);this.barnesHutTree=v},e._updateBranchMass=function(t,e){var i=t.mass+e.mass,s=1/i;t.centerOfMass.x=t.centerOfMass.x*t.mass+e.x*e.mass,t.centerOfMass.x*=s,t.centerOfMass.y=t.centerOfMass.y*t.mass+e.y*e.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}}])}); +!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 n=i[s]={exports:{},id:s,loaded:!1};return t[s].call(n.exports,n,n.exports,e),n.loaded=!0,n.exports}var i={};return e.m=t,e.c=i,e.p="",e(0)}([function(t,e,i){e.util=i(1),e.DOMutil=i(2),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(18),CurrentTime:i(19),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(40),e.hammer=i(41)},function(module,exports,__webpack_require__){var moment=__webpack_require__(40);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 n in s)s.hasOwnProperty(n)&&(t[n]=s[n])}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),n={h:s.h,s:.45*s.s,v:Math.min(1,1.05*s.v)},o={h:s.h,s:Math.min(1,1.25*s.v),v:.6*s.v},r=exports.HSVToHex(o.h,o.h,o.v),a=exports.HSVToHex(n.h,n.s,n.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)),n=exports.GiveDec(t.substring(3,4)),o=exports.GiveDec(t.substring(4,5)),r=exports.GiveDec(t.substring(5,6)),a=16*e+i,h=16*s+n,i=16*o+r;return{r:a,g:h,b:i}},exports.RGBToHex=function(t,e,i){var s=exports.GiveHex(Math.floor(t/16)),n=exports.GiveHex(t%16),o=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+n+o+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)),n=Math.max(t,Math.max(e,i));if(s==n)return{h:0,s:0,v:s};var o=t==s?e-i:i==s?t-e:i-t,r=t==s?3:i==s?1:5,a=60*(r-o/(n-s))/360,h=(n-s)/n,d=n;return{h:a,s:h,v:d}},exports.HSVToRGB=function(t,e,i){var s,n,o,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,n=l,o=h;break;case 1:s=d,n=i,o=h;break;case 2:s=h,n=i,o=l;break;case 3:s=h,n=d,o=i;break;case 4:s=l,n=h,o=i;break;case 5:s=i,n=h,o=d}return{r:Math.floor(255*s),g:Math.floor(255*n),b:Math.floor(255*o)}},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;)n=void 0===s?o[p][i]:o[p][i][s],o[p].isVisible(e)?h=!0:(n=r&&console.log("BinarySearch too many iterations. Aborting.")}return p},exports.binarySearchGeneric=function(t,e,i,s){var n,o,r,a,h=1e4,d=0,l=t,c=!1,u=0,p=l.length,f=u,g=p,m=Math.floor(.5*(p+u));if(0==p)m=-1;else if(1==p)r=l[m][i],m=r==e?0:-1;else{for(p-=1;0==c&&h>d;)o=l[Math.max(0,m-1)][i],r=l[m][i],a=l[Math.min(l.length-1,m+1)][i],r==e||e>o&&r>e||e>r&&a>e?(c=!0,r!=e&&("before"==s?e>o&&r>e&&(m=Math.max(0,m-1)):e>r&&a>e&&(m=Math.min(l.length-1,m+1)))):(e>r?f=Math.floor(.5*(p+u)):g=Math.floor(.5*(p+u)),n=Math.floor(.5*(p+u)),u==f&&p==g?(m=-1,c=!0):(p=g,u=f,m=Math.floor(.5*(p+u)))),d++;d>=h&&console.log("BinarySearch too many iterations. Aborting.")}return m}},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,n,o){var r;return"circle"==s.options.drawPoints.style?(r=e.getSVGElement("circle",n,o),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",n,o),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,n,o,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",n),h.setAttributeNS(null,"class",o)}},function(t,e,i){function s(t,e){if(!t||Array.isArray(t)||n.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 n=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 n=0;nr;r++)i=o._addItem(t[r]),s.push(i);else if(n.isDataTable(t))for(var h=this._getColumnNames(t),d=0,l=t.getNumberOfRows();l>d;d++){for(var c={},u=0,p=h.length;p>u;u++){var f=h[u];c[f]=t.getValue(d,u)}i=o._addItem(c),s.push(i)}else{if(!(t instanceof Object))throw new Error("Unknown dataType");i=o._addItem(t),s.push(i)}return s.length&&this._trigger("add",{items:s},e),s},s.prototype.update=function(t,e){var i=[],s=[],o=this,r=o._fieldId,a=function(t){var e=t[r];o._data[e]?(e=o._updateItem(t),s.push(e)):(e=o._addItem(t),i.push(e))};if(Array.isArray(t))for(var h=0,d=t.length;d>h;h++)a(t[h]);else if(n.isDataTable(t))for(var l=this._getColumnNames(t),c=0,u=t.getNumberOfRows();u>c;c++){for(var p={},f=0,g=l.length;g>f;f++){var m=l[f];p[m]=t.getValue(c,f)}a(p)}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,o=this,r=n.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!=n.getType(s))throw new Error('Type of parameter "data" ('+n.getType(s)+") does not correspond with specified options.type ("+i.type+")");if("DataTable"==a&&!n.isDataTable(s))throw new Error('Parameter "data" must be a DataTable when options.type is "DataTable"')}else a=s&&"DataTable"==n.getType(s)?"DataTable":"Array";var d,l,c,u,p=i&&i.type||this._options.type,f=i&&i.filter,g=[];if(void 0!=t)d=o._getItem(t,p),f&&!f(d)&&(d=null);else if(void 0!=e)for(c=0,u=e.length;u>c;c++)d=o._getItem(e[c],p),(!f||f(d))&&g.push(d);else for(l in this._data)this._data.hasOwnProperty(l)&&(d=o._getItem(l,p),(!f||f(d))&&g.push(d));if(i&&i.order&&void 0==t&&this._sort(g,i.order),i&&i.fields){var m=i.fields;if(void 0!=t)d=this._filterFields(d,m);else for(c=0,u=g.length;u>c;c++)g[c]=this._filterFields(g[c],m)}if("DataTable"==a){var v=this._getColumnNames(s);if(void 0!=t)o._appendRow(s,v,d);else for(c=0;cc;c++)s.push(g[c]);return s}return g},s.prototype.getIds=function(t){var e,i,s,n,o,r=this._data,a=t&&t.filter,h=t&&t.order,d=t&&t.type||this._options.type,l=[];if(a)if(h){o=[];for(s in r)r.hasOwnProperty(s)&&(n=this._getItem(s,d),a(n)&&o.push(n));for(this._sort(o,h),e=0,i=o.length;i>e;e++)l[e]=o[e][this._fieldId]}else for(s in r)r.hasOwnProperty(s)&&(n=this._getItem(s,d),a(n)&&l.push(n[this._fieldId]));else if(h){o=[];for(s in r)r.hasOwnProperty(s)&&o.push(r[s]);for(this._sort(o,h),e=0,i=o.length;i>e;e++)l[e]=o[e][this._fieldId]}else for(s in r)r.hasOwnProperty(s)&&(n=r[s],l.push(n[this._fieldId]));return l},s.prototype.getDataSet=function(){return this},s.prototype.forEach=function(t,e){var i,s,n=e&&e.filter,o=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,o),(!n||n(i))&&t(i,s))},s.prototype.map=function(t,e){var i,s=e&&e.filter,n=e&&e.type||this._options.type,o=[],r=this._data;for(var a in r)r.hasOwnProperty(a)&&(i=this._getItem(a,n),(!s||s(i))&&o.push(t(i,a)));return e&&e.order&&this._sort(o,e.order),o},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(n.isString(e)){var i=e;t.sort(function(t,e){var s=t[i],n=e[i];return s>n?1:n>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,n,o=[];if(Array.isArray(t))for(i=0,s=t.length;s>i;i++)n=this._remove(t[i]),null!=n&&o.push(n);else n=this._remove(t),null!=n&&o.push(n);return o.length&&this._trigger("remove",{items:o},e),o},s.prototype._remove=function(t){if(n.isNumber(t)||n.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 n in e)if(e.hasOwnProperty(n)){var o=e[n],r=o[t];null!=r&&(!i||r>s)&&(i=o,s=r)}return i},s.prototype.min=function(t){var e=this._data,i=null,s=null;for(var n in e)if(e.hasOwnProperty(n)){var o=e[n],r=o[t];null!=r&&(!i||s>r)&&(i=o,s=r)}return i},s.prototype.distinct=function(t){var e,i=this._data,s=[],o=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(o)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(),n=0,o=e.length;o>n;n++){var r=e[n];t.setValue(s,n,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 n=i(1),o=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 n in this._ids)this._ids.hasOwnProperty(n)&&e.push(n);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++)n=e[i],this._ids[n]=!0;this._trigger("add",{items:e}),this._data.on&&this._data.on("*",this.listener)}},s.prototype.get=function(){var t,e,i,s=this,o=n.getType(arguments[0]);"String"==o||"Number"==o||"Array"==o?(t=arguments[0],e=arguments[1],i=arguments[2]):(e=arguments[0],i=arguments[1]);var r=n.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,n,o,r,a=e&&e.items,h=this._data,d=[],l=[],c=[];if(a&&h){switch(t){case"add":for(s=0,n=a.length;n>s;s++)o=a[s],r=this.get(o),r&&(this._ids[o]=!0,d.push(o));break;case"update":for(s=0,n=a.length;n>s;s++)o=a[s],r=this.get(o),r?this._ids[o]?l.push(o):(this._ids[o]=!0,d.push(o)):this._ids[o]&&(delete this._ids[o],c.push(o));break;case"remove":for(s=0,n=a.length;n>s;s++)o=a[s],this._ids[o]&&(delete this._ids[o],c.push(o))}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=o.prototype.on,s.prototype.off=o.prototype.off,s.prototype._trigger=o.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 n=i(45),o=i(3),r=i(4),a=i(1),h=i(9),d=i(8),l=i(6),c=i(7),u=i(10),p=i(11);n(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 g=(t-u)/(f-u),m=240*g,v=this._hsv2rgb(m,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,o)}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 p(this.valueMin,this.valueMax,(this.valueMax-this.valueMin)/5,!0);for(b.start(),b.getCurrent()0?this.yMin:this.yMax,n=this._convert3Dto2D(new h(x,r,this.zMin)),Math.cos(2*_)>0?(m.textAlign="center",m.textBaseline="top",n.y+=b):Math.sin(2*_)<0?(m.textAlign="right",m.textBaseline="middle"):(m.textAlign="left",m.textBaseline="middle"),m.fillStyle=this.colorAxis,m.fillText(" "+i.getCurrent()+" ",n.x,n.y),i.next()}for(m.lineWidth=1,s=void 0===this.defaultYStep,i=new p(this.yMin,this.yMax,this.yStep,s),i.start(),i.getCurrent()0?this.xMin:this.xMax,n=this._convert3Dto2D(new h(o,i.getCurrent(),this.zMin)),Math.cos(2*_)<0?(m.textAlign="center",m.textBaseline="top",n.y+=b):Math.sin(2*_)>0?(m.textAlign="right",m.textBaseline="middle"):(m.textAlign="left",m.textBaseline="middle"),m.fillStyle=this.colorAxis,m.fillText(" "+i.getCurrent()+" ",n.x,n.y),i.next();for(m.lineWidth=1,s=void 0===this.defaultZStep,i=new p(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(o,r,i.getCurrent())),m.strokeStyle=this.colorAxis,m.beginPath(),m.moveTo(t.x,t.y),m.lineTo(t.x-b,t.y),m.stroke(),m.textAlign="right",m.textBaseline="middle",m.fillStyle=this.colorAxis,m.fillText(i.getCurrent()+" ",t.x-5,t.y),i.next();m.lineWidth=1,t=this._convert3Dto2D(new h(o,r,this.zMin)),e=this._convert3Dto2D(new h(o,r,this.zMax)),m.strokeStyle=this.colorAxis,m.beginPath(),m.moveTo(t.x,t.y),m.lineTo(e.x,e.y),m.stroke(),m.lineWidth=1,u=this._convert3Dto2D(new h(this.xMin,this.yMin,this.zMin)),f=this._convert3Dto2D(new h(this.xMax,this.yMin,this.zMin)),m.strokeStyle=this.colorAxis,m.beginPath(),m.moveTo(u.x,u.y),m.lineTo(f.x,f.y),m.stroke(),u=this._convert3Dto2D(new h(this.xMin,this.yMax,this.zMin)),f=this._convert3Dto2D(new h(this.xMax,this.yMax,this.zMin)),m.strokeStyle=this.colorAxis,m.beginPath(),m.moveTo(u.x,u.y),m.lineTo(f.x,f.y),m.stroke(),m.lineWidth=1,t=this._convert3Dto2D(new h(this.xMin,this.yMin,this.zMin)),e=this._convert3Dto2D(new h(this.xMin,this.yMax,this.zMin)),m.strokeStyle=this.colorAxis,m.beginPath(),m.moveTo(t.x,t.y),m.lineTo(e.x,e.y),m.stroke(),t=this._convert3Dto2D(new h(this.xMax,this.yMin,this.zMin)),e=this._convert3Dto2D(new h(this.xMax,this.yMax,this.zMin)),m.strokeStyle=this.colorAxis,m.beginPath(),m.moveTo(t.x,t.y),m.lineTo(e.x,e.y),m.stroke();var w=this.xLabel;w.length>0&&(c=.1/this.scale.y,o=(this.xMin+this.xMax)/2,r=Math.cos(_)>0?this.yMin-c:this.yMax+c,n=this._convert3Dto2D(new h(o,r,this.zMin)),Math.cos(2*_)>0?(m.textAlign="center",m.textBaseline="top"):Math.sin(2*_)<0?(m.textAlign="right",m.textBaseline="middle"):(m.textAlign="left",m.textBaseline="middle"),m.fillStyle=this.colorAxis,m.fillText(w,n.x,n.y));var S=this.yLabel;S.length>0&&(l=.1/this.scale.x,o=Math.sin(_)>0?this.xMin-l:this.xMax+l,r=(this.yMin+this.yMax)/2,n=this._convert3Dto2D(new h(o,r,this.zMin)),Math.cos(2*_)<0?(m.textAlign="center",m.textBaseline="top"):Math.sin(2*_)>0?(m.textAlign="right",m.textBaseline="middle"):(m.textAlign="left",m.textBaseline="middle"),m.fillStyle=this.colorAxis,m.fillText(S,n.x,n.y));var M=this.zLabel;M.length>0&&(d=30,o=Math.cos(_)>0?this.xMin:this.xMax,r=Math.sin(_)<0?this.yMin:this.yMax,a=(this.zMin+this.zMax)/2,n=this._convert3Dto2D(new h(o,r,a)),m.textAlign="right",m.textBaseline="middle",m.fillStyle=this.colorAxis,m.fillText(M,n.x-d,n.y))},s.prototype._hsv2rgb=function(t,e,i){var s,n,o,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,n=h,o=0;break;case 1:s=h,n=r,o=0;break;case 2:s=0,n=r,o=h;break;case 3:s=0,n=h,o=r;break;case 4:s=h,n=0,o=r;break;case 5:s=r,n=0,o=h;break;default:s=0,n=0,o=0}return"RGB("+parseInt(255*s)+","+parseInt(255*n)+","+parseInt(255*o)+")"},s.prototype._redrawDataGrid=function(){var t,e,i,n,o,r,a,d,l,c,u,p,f,g=this.frame.canvas,m=g.getContext("2d");if(!(void 0===this.dataPoints||this.dataPoints.length<=0)){for(o=0;o0}else r=!0;r?(f=(t.point.z+e.point.z+i.point.z+n.point.z)/4,c=240*(1-(f-this.zMin)*this.scale.z/this.verticalRatio),u=1,this.showShadow?(p=Math.min(1+S.x/M/2,1),a=this._hsv2rgb(c,u,p),d=a):(p=1,a=this._hsv2rgb(c,u,p),d=this.colorAxis)):(a="gray",d=this.colorAxis),l=.5,m.lineWidth=l,m.fillStyle=a,m.strokeStyle=d,m.beginPath(),m.moveTo(t.screen.x,t.screen.y),m.lineTo(e.screen.x,e.screen.y),m.lineTo(n.screen.x,n.screen.y),m.lineTo(i.screen.x,i.screen.y),m.closePath(),m.fill(),m.stroke()}}else for(o=0;ou&&(u=0);var p,f,g;this.style===s.STYLE.DOTCOLOR?(p=240*(1-(d.point.value-this.valueMin)*this.scale.value),f=this._hsv2rgb(p,1,1),g=this._hsv2rgb(p,1,.8)):this.style===s.STYLE.DOTSIZE?(f=this.colorDot,g=this.colorDotBorder):(p=240*(1-(d.point.z-this.zMin)*this.scale.z/this.verticalRatio),f=this._hsv2rgb(p,1,1),g=this._hsv2rgb(p,1,.8)),i.lineWidth=1,i.strokeStyle=g,i.fillStyle=f,i.beginPath(),i.arc(d.screen.x,d.screen.y,u,0,2*Math.PI,!0),i.fill(),i.stroke()}}},s.prototype._redrawDataBar=function(){var t,e,i,n,o=this.frame.canvas,r=o.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,n=this.startArmRotation.vertical+i/200,o=4,r=Math.sin(o/360*2*Math.PI);Math.abs(Math.sin(s))0?1:0>t?-1:0}var s=e[0],n=e[1],o=e[2],r=i((n.x-s.x)*(t.y-s.y)-(n.y-s.y)*(t.x-s.x)),a=i((o.x-n.x)*(t.y-n.y)-(o.y-n.y)*(t.x-n.x)),h=i((s.x-o.x)*(t.y-o.y)-(s.y-o.y)*(t.x-o.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,n=100,o=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--){o=this.dataPoints[i];var l=o.surfaces;if(l)for(var c=l.length-1;c>=0;c--){var u=l[c],p=u.corners,f=[p[0].screen,p[1].screen,p[2].screen],g=[p[2].screen,p[3].screen,p[0].screen];if(this._insideTriangle(h,f)||this._insideTriangle(h,g))return o}}else for(i=0;ib)&&n>b&&(a=b,r=o)}}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 n=e.offsetWidth,o=e.offsetHeight,r=i.offsetHeight,a=s.offsetWidth,h=s.offsetHeight,d=t.screen.x-n/2;d=Math.min(Math.max(d,10),this.frame.clientWidth-10-n),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-o+"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 n=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 n(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),n.preventDefault()},s.prototype._onMouseUp=function(){this.frame.style.cursor="auto",n.removeEventListener(document,"mousemove",this.onmousemove),n.removeEventListener(document,"mouseup",this.onmouseup),n.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))),n=5*Math.pow(10,Math.round(e(t/5))),o=i;return Math.abs(s-t)<=Math.abs(o-t)&&(o=s),Math.abs(n-t)<=Math.abs(o-t)&&(o=n),0>=o&&(o=1),o},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 o in h.prototype)h.prototype.hasOwnProperty(o)&&!s.prototype.hasOwnProperty(o)&&(s.prototype[o]=h.prototype[o]);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=n.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 u(this.body),this.components.push(this.itemSet),this.itemsData=null,this.groupsData=null,i&&this.setOptions(i),e?this.setItems(e):this.redraw()}var n=(i(45),i(41),i(1)),o=i(3),r=i(4),a=i(15),h=i(!function(){var t=new Error('Cannot find module "./Core"');throw t.code="MODULE_NOT_FOUND",t}()),d=i(27),l=i(19),c=i(20),u=i(24);s.prototype.setOptions=function(t){if(t){var e=["width","height","minHeight","maxHeight","autoResize","start","end","orientation"];n.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 o||t instanceof r?t:new o(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?n.convert(this.options.start,"Date"):null,a="end"in this.options?n.convert(this.options.end,"Date"):null;this.setWindow(s,a)}},s.prototype.setGroups=function(t){var e;e=t?t instanceof o||t instanceof r?t:new o(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()||[]},t.exports=s},function(t,e,i){function s(t,e,i,o){for(var r in h.prototype)h.prototype.hasOwnProperty(r)&&!s.prototype.hasOwnProperty(r)&&(s.prototype[r]=h.prototype[r]);var p=this;this.defaultOptions={start:null,end:null,autoResize:!0,orientation:"bottom",width:null,height:null,maxHeight:null,minHeight:null},this.options=n.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:p._toScreen.bind(p),toGlobalScreen:p._toGlobalScreen.bind(p),toTime:p._toTime.bind(p),toGlobalTime:p._toGlobalTime.bind(p)}},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 u(this.body),this.components.push(this.linegraph),this.itemsData=null,this.groupsData=null,i&&this.setOptions(i),o&&this.setGroups(o),e?this.setItems(e):this.redraw()}var n=(i(45),i(41),i(1)),o=i(3),r=i(4),a=i(15),h=i(!function(){var t=new Error('Cannot find module "./Core"');throw t.code="MODULE_NOT_FOUND",t}()),d=i(27),l=i(19),c=i(20),u=i(26);s.prototype.setOptions=function(t){if(t){var e=["width","height","minHeight","maxHeight","autoResize","start","end","orientation"];n.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 o||t instanceof r?t:new o(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?n.convert(this.options.start,"Date"):null,a="end"in this.options?n.convert(this.options.end,"Date"):null;this.setWindow(s,a)}},s.prototype.setGroups=function(t){var e;e=t?t instanceof o||t instanceof r?t:new o(t):null,this.groupsData=e,this.linegraph.setGroups(e)},t.exports=s},function(t){function e(t,e,i,s,n){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,n)}e.prototype.setRange=function(t,e,i,s,n){this._start=t,this._end=e,t==e&&(this._start=t-.75,this._end=e+1),this.autoScale&&this.setMinimumStep(i,s,n),this.setFirst()},e.prototype.setMinimumStep=function(t,e){var i=this._end-this._start,s=1.1*i,n=t*(s/e),o=Math.round(Math.log(s)/Math.LN10),r=-1,a=Math.pow(10,o),h=0;0>o&&(h=o);for(var d=!1,l=h;Math.abs(l)<=Math.abs(o);l++){a=Math.pow(10,l);for(var c=0;c=n){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 n(t){if("horizontal"!=t&&"vertical"!=t)throw new TypeError('Unknown direction "'+t+'". Choose "horizontal" or "vertical".')}function o(t,e){return{x:t.pageX-r.getAbsoluteLeft(e),y:t.pageY-r.getAbsoluteTop(e)}}var r=i(1),a=i(42),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,n=null!=e?r.convert(e,"Date").valueOf():this.end,o=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(n)||null===n)throw new Error('Invalid end "'+e+'"');if(s>n&&(n=s),null!==a&&a>s&&(i=a-s,s+=i,n+=i,null!=o&&n>o&&(n=o)),null!==o&&n>o&&(i=n-o,s-=i,n-=i,null!=a&&a>s&&(s=a)),null!==this.options.zoomMin){var h=parseFloat(this.options.zoomMin);0>h&&(h=0),h>n-s&&(this.end-this.start===h?(s=this.start,n=this.end):(i=h-(n-s),s-=i/2,n+=i/2))}if(null!==this.options.zoomMax){var d=parseFloat(this.options.zoomMax);0>d&&(d=0),n-s>d&&(this.end-this.start===d?(s=this.start,n=this.end):(i=n-s-d,s+=i/2,n-=i/2))}var l=this.start!=s||this.end!=n;return this.start=s,this.end=n,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(n(e),this.props.touch.allowDragging){var i="horizontal"==e?t.gesture.deltaX:t.gesture.deltaY,s=this.props.touch.end-this.props.touch.start,o="horizontal"==e?this.body.domProps.center.width:this.body.domProps.center.height,r=-i/o*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),n=o(s.center,this.body.dom.center),r=this._pointerToDate(n);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=o(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),n=parseInt(i+(this.props.touch.end-i)*e);this.setRange(s,n)}},s.prototype._pointerToDate=function(t){var e,i=this.options.direction;if(n(i),"horizontal"==i){var s=this.body.domProps.center.width;return e=this.conversion(s),t.x/e.scale+e.offset}var o=this.body.domProps.center.height;return e=this.conversion(o),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,n=this.end-i;this.setRange(s,n)},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 n,o;if(s)for(n=0,o=t.length;o>n;n++)t[n].top=null;for(n=0,o=t.length;o>n;n++){var r=t[n];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 n=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,n=864e5,o=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*n>t&&(this.scale=s.SCALE.DAY,this.step=5),2*n>t&&(this.scale=s.SCALE.DAY,this.step=2),n>t&&(this.scale=s.SCALE.DAY,this.step=1),n/2>t&&(this.scale=s.SCALE.WEEKDAY,this.step=1),4*o>t&&(this.scale=s.SCALE.HOUR,this.step=4),o>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 n=this.step>5?this.step/2:1;e.setMilliseconds(Math.round(e.getMilliseconds()/n)*n)}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 n(t).format("SSS");case s.SCALE.SECOND:return n(t).format("s");case s.SCALE.MINUTE:return n(t).format("HH:mm");case s.SCALE.HOUR:return n(t).format("HH:mm");case s.SCALE.WEEKDAY:return n(t).format("ddd D");case s.SCALE.DAY:return n(t).format("D");case s.SCALE.MONTH:return n(t).format("MMM");case s.SCALE.YEAR:return n(t).format("YYYY");default:return""}},s.prototype.getLabelMajor=function(t){switch(void 0==t&&(t=this.current),this.scale){case s.SCALE.MILLISECOND:return n(t).format("HH:mm:ss");case s.SCALE.SECOND:return n(t).format("D MMMM HH:mm");case s.SCALE.MINUTE:case s.SCALE.HOUR:return n(t).format("ddd D MMMM");case s.SCALE.WEEKDAY:case s.SCALE.DAY:return n(t).format("MMMM YYYY");case s.SCALE.MONTH:return n(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=n.extend({},this.defaultOptions),this._create(),this.setOptions(e)}var n=i(1),o=i(18);s.prototype=new o,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&&n.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=o.extend({},this.defaultOptions),this.customTime=new Date,this.eventParams={},this._create(),this.setOptions(e)}var n=i(41),o=i(1),r=i(18);s.prototype=new r,s.prototype.setOptions=function(t){t&&o.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=n(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=n.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=n.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 n=i(1),o=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"];n.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(){o.prepareElements(this.svgElements);var t,e=this.options.iconWidth,i=15,s=4,n=s+.5*i;t="left"==this.options.orientation?s:this.width-e-s;for(var r in this.groups)this.groups.hasOwnProperty(r)&&(this.groups[r].drawIcon(t,n,this.svgElements,this.svg,e,i),n+=i+s);o.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;if(0==this.amountOfGroups)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 e=this.props,i=this.dom.frame;i.className="dataaxis",this._calculateCharSize();var s=this.options.orientation,n=this.options.showMinorLabels,o=this.options.showMajorLabels;e.minorLabelHeight=n?e.minorCharHeight:0,e.majorLabelHeight=o?e.majorCharHeight:0,e.minorLineWidth=this.body.dom.backgroundHorizontal.offsetWidth-this.lineOffset-this.width+2*this.options.minorLinesOffset,e.minorLineHeight=1,e.majorLineWidth=this.body.dom.backgroundHorizontal.offsetWidth-this.lineOffset-this.width+2*this.options.majorLinesOffset,e.majorLineHeight=1,"left"==s?(i.style.top="0",i.style.left="0",i.style.bottom="",i.style.width=this.width+"px",i.style.height=this.height+"px"):(i.style.top="",i.style.bottom="0",i.style.left="0",i.style.width=this.width+"px",i.style.height=this.height+"px"),t=this._redrawLabels(),1==this.options.icons&&this._redrawGroupIcons()}return t},s.prototype._redrawLabels=function(){o.prepareElements(this.DOMelements);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 n=this.height/s,r=0;if(0==this.master){s=this.stepPixelsForced,r=Math.round(this.height/s-n);for(var h=0;.5*r>h;h++)i.previous();n=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/((n-1)*i.step);var p=1==this.options.icons?this.options.iconWidth+this.options.labelOffsetX+15:this.options.labelOffsetX+15;return this.maxLabelSize>this.width-p&&1==this.options.visible?(this.width=this.maxLabelSize+p,this.options.width=this.width+"px",o.cleanupElements(this.DOMelements),this.redraw(),!0):this.maxLabelSizethis.minWidth?(this.width=Math.max(this.minWidth,this.maxLabelSize+p),this.options.width=this.width+"px",o.cleanupElements(this.DOMelements),this.redraw(),!0):(o.cleanupElements(this.DOMelements),!1)},s.prototype._redrawLabel=function(t,e,i,s,n){var r=o.getDOMElement("div",this.DOMelements,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*n+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,n.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 u=this.dom.foreground;this.top=u.offsetTop,this.left=u.offsetLeft,this.width=u.offsetWidth,s=n.updateProperty(this,"height",a)||s,s=n.updateProperty(this.props.label,"width",this.dom.inner.clientWidth)||s,s=n.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 p=0,f=this.visibleItems.length;f>p;p++){var g=this.visibleItems[p];g.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=n.toArray(this.items);this.orderedItems.byStart=t,this.orderedItems.byEnd=this._constructByEndArray(t),o.orderByStart(this.orderedItems.byStart),o.orderByEnd(this.orderedItems.byEnd)},s.prototype._constructByEndArray=function(t){for(var e=[],i=0;i0)for(o=0;o=0&&!this._checkIfInvisible(t.byStart[o],r,i);o--);for(o=s+1;o=0&&!this._checkIfInvisible(t.byEnd[o],r,i);o--);for(o=a+1;oe;e++)s=this.selection[e],n=this.items[s],n&&n.unselect();for(this.selection=[],e=0,i=t.length;i>e;e++)s=t[e],n=this.items[s],n&&(this.selection.push(s),n.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 n in this.groups)if(this.groups.hasOwnProperty(n))for(var o=this.groups[n],r=o.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=o.option.asSize,s=this.options,n=s.orientation,r=!1,a=this.dom.frame,h=s.editable.updateTime||s.editable.updateGroup;a.className="itemset"+(h?" editable":""),r=this._orderGroups()||r;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,u=this._firstGroup(),p={item:t.item,axis:t.axis},f={item:t.item,axis:t.item.vertical/2},g=0,m=t.axis+t.item.vertical;return o.forEach(this.groups,function(t){var i=t==u?p:f,s=t.redraw(e,i,c);r=s||r,g+=t.height}),g=Math.max(g,m),this.stackDirty=!1,a.style.height=i(g),this.props.top=a.offsetTop,this.props.left=a.offsetLeft,this.props.width=a.offsetWidth,this.props.height=g,this.dom.axis.style.top=i("top"==n?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",r=this._isResized()||r},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[p];return i||null},s.prototype._updateUngrouped=function(){var t=this.groups[p];if(this.groupsData)t&&(t.hide(),delete this.groups[p]);else if(!t){var e=null,i=null;t=new d(e,i,this),this.groups[p]=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 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()}},s.prototype.getItems=function(){return this.itemsData},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._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),n=e.items[t],o=i.type||e.options.type||(i.end?"range":"box"),r=s.types[o];if(n&&(r&&n instanceof r?e._updateItem(n,i):(e._removeItem(n),n=null)),!n){if(!r)throw new TypeError("rangeoverflow"==o?'Item type "rangeoverflow" is deprecated. Use css styling instead: .vis.timeline .item.range .content {overflow: visible;}':'Unknown item type "'+o+'"');n=new r(i,e.conversion,e.options),n.id=t,e._addItem(n)}}),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(){o.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==p)throw new Error("Illegal group id. "+t+" is a reserved id.");var n=Object.create(e.options);o.extend(n,{height:null}),s=new d(t,i,e),e.groups[t]=s;for(var r in e.items)if(e.items.hasOwnProperty(r)){var a=e.items[r];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=!o.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:p,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 n=this.groupsData?t.data.group:p,o=this.groups[n];o&&o.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:p,s=this.groups[i];s&&s.remove(t)},s.prototype._constructByEndArray=function(t){for(var e=[],i=0;i0||n.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,n=s.itemFromTarget(t);if(n){var r=e.itemsData.get(n.id);this.options.onUpdate(r,function(t){t&&e.itemsData.update(t)})}else{var a=o.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]=o.randomUUID();var u=s.groupFromTarget(t);u&&(l.group=u.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 n=e.indexOf(i.id);-1==n?e.push(i.id):e.splice(n,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=n.extend({},this.defaultOptions),this.svgElements={},this.dom={},this.groups={},this.amountOfGroups=0,this._create(),this.setOptions(e)}var n=i(1),o=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"];n.selectiveDeepExtend(e,this.options,t)},s.prototype.redraw=function(){if(0==this.options[this.side].visible||0==this.amountOfGroups||0==this.options.enabled)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 t="";for(var e in this.groups)this.groups.hasOwnProperty(e)&&(t+=this.groups[e].content+"
");this.dom.textArea.innerHTML=t,this.dom.textArea.style.lineHeight=.75*this.options.iconSize+this.options.iconSpacing+"px"}},s.prototype.drawLegendIcons=function(){if(this.dom.frame.parentNode){o.prepareElements(this.svgElements);var t=window.getComputedStyle(this.dom.frame).paddingTop,e=Number(t.replace("px","")),i=e,s=this.options.iconSize,n=.75*this.options.iconSize,r=e+.5*n+3;this.svg.style.width=s+5+e+"px";for(var a in this.groups)this.groups.hasOwnProperty(a)&&(this.groups[a].drawIcon(i,r,this.svgElements,this.svg,s,n),r+=n+this.options.iconSpacing);o.cleanupElements(this.svgElements)}},t.exports=s},function(t,e,i){function s(t,e){this.id=n.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,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=n.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,n=t*s;i.svg.style.left=-i.width-n+"px"}}}),this.body.emitter.on("rangechanged",function(){i.lastStart=i.body.range.start,i.svg.style.left=n.option.asSize(-i.width),i._updateGraph.apply(i)}),this._create(),this.body.emitter.emit("change")}var n=i(1),o=i(2),r=i(3),a=i(4),h=i(18),d=i(21),l=i(22),c=i(25),u="__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"];n.selectiveDeepExtend(e,this.options,t),n.mergeOptions(this.options,t,"catmullRom"),n.mergeOptions(this.options,t,"drawPoints"),n.mergeOptions(this.options,t,"shaded"),n.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(u)&&this.groups[u].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&&(n.forEach(this.itemListeners,function(t,e){s.off(e,t)}),e=s.getIds(),this._onRemove(e)),this.itemsData){var o=this.id;n.forEach(this.itemListeners,function(t,e){i.itemsData.on(e,t,o)}),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&&(n.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;n.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;sp){e.push(m);break}e.push(m)}}else for(var g=0;gu&&m.x0){for(var u=0;ui?i:a,d=s>d?s:d):(r=!0,h=h>i?i:h,l=s>l?s:l)}1==o&&this.yAxisLeft.setRange(a,d),1==r&&this.yAxisRight.setRange(h,l)}return n=this._toggleAxisVisiblity(o,this.yAxisLeft)||n,n=this._toggleAxisVisiblity(r,this.yAxisRight)||n,1==r&&1==o?(this.yAxisLeft.drawIcons=!0,this.yAxisRight.drawIcons=!0):(this.yAxisLeft.drawIcons=!1,this.yAxisRight.drawIcons=!1),this.yAxisRight.master=!o,0==this.yAxisRight.master?(1==r&&(this.yAxisLeft.lineOffset=this.yAxisRight.width),n=this.yAxisLeft.redraw()||n,this.yAxisRight.stepPixelsForced=this.yAxisLeft.stepPixels,n=this.yAxisRight.redraw()||n):n=this.yAxisRight.redraw()||n,n},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){var i,s=.1*e.options.barChart.width,n=0,r=e.options.barChart.width;"left"==e.options.barChart.align?n-=.5*r:"right"==e.options.barChart.align&&(n+=.5*r);for(var a=0;a0&&(i=Math.min(i,Math.abs(t[a-1].x-t[a].x))),r>i&&(r=s>i?s:i),o.drawBar(t[a].x+n,t[a].y,r,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,n)}},s.prototype._drawLineGraph=function(t,e){if(null!=t&&t.length>0){var i,s,n=Number(this.svg.style.height.replace("px",""));if(i=o.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=o.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+","+n+" "+s+"L"+t[t.length-1].x+","+n,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,n){void 0===n&&(n=0);for(var r=0;ru;u+=r)i=o(t[u].x)+this.width-1,s=t[u].y,n.push({x:i,y:s}),h=h>s?s:h,d=s>d?s:d;return{min:h,max:d,data:n}},s.prototype._convertYvalues=function(t,e){var i,s,n=[],o=this.yAxisLeft,r=Number(this.svg.style.height.replace("px",""));"right"==e.options.yAxisOrientation&&(o=this.yAxisRight);for(var a=0;al;l++)e=0==l?t[0]:t[l-1],i=t[l],s=t[l+1],n=d>l+2?t[l+2]:s,o={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-n.x)*h,y:(i.y+6*s.y-n.y)*h},a+="C"+o.x+","+o.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,n,o,r,a,h,d,l,c,u,p,f,g,m,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],n=t[M],o=t[M+1],r=S>M+2?t[M+2]:o,d=Math.sqrt(Math.pow(s.x-n.x,2)+Math.pow(s.y-n.y,2)),l=Math.sqrt(Math.pow(n.x-o.x,2)+Math.pow(n.y-o.y,2)),c=Math.sqrt(Math.pow(o.x-r.x,2)+Math.pow(o.y-r.y,2)),m=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),u=2*_+3*x*v+b,p=2*y+3*m*v+b,f=3*x*(x+v),f>0&&(f=1/f),g=3*m*(m+v),g>0&&(g=1/g),a={x:(-b*s.x+u*n.x+_*o.x)*f,y:(-b*s.y+u*n.y+_*o.y)*f},h={x:(y*n.x+p*o.x-b*r.x)*g,y:(y*n.y+p*o.y-b*r.y)*g},0==a.x&&0==a.y&&(a=n),0==h.x&&0==h.y&&(h=o),w+="C"+a.x+","+a.y+" "+h.x+","+h.y+" "+o.x+","+o.y+" ";return w},s.prototype._linear=function(t){for(var e="",i=0;id;){d++;var l=o.getCurrent(),c=this.body.util.toScreen(l),u=o.isMajor();this.options.showMinorLabels&&this._repaintMinorText(c,o.getLabelMinor(),t),u&&this.options.showMajorLabels?(c>0&&(void 0==h&&(h=c),this._repaintMajorText(c,o.getLabelMajor(),t)),this._repaintMajorLine(c,t)):this._repaintMinorLine(c,t),o.next()}if(this.options.showMajorLabels){var p=this.body.util.toTime(0),f=o.getLabelMajor(p),g=f.length*(this.props.majorCharWidth||10)+10;(void 0==h||h>g)&&this._repaintMajorText(0,f,t)}n.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 n=document.createTextNode("");s=document.createElement("div"),s.appendChild(n),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 n=document.createTextNode(e);s=document.createElement("div"),s.className="text major",s.appendChild(n),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 n=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",n(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);n.call(this,t,e,i)}var n=i(28);s.prototype=new n(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),n=this.conversion.toScreen(this.data.end),o=this.options.padding;-i>s&&(s=-i),n>2*i&&(n=2*i);var r=Math.max(n-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,n-s-e.content.width-2*o):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,n(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,n(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.width="100%",this.height="100%",this.renderRefreshRate=60,this.renderTimestep=1e3/this.renderRefreshRate,this.renderTime=.5*this.renderTimestep,this.maxPhysicsTicksPerRender=3,this.physicsDiscreteStepsize=.5,this.stabilize=!0,this.selectable=!0,this.initializing=!0,this.triggerFunctions={add:null,edit:null,editEdge:null,connect:null,del:null},this.constants={nodes:{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,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},this.hoverObj={nodes:{},edges:{}},this.controlNodesActive=!1; +var n=this;this.groups=new p,this.images=new f,this.images.setOnloadCallback(function(){n._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){n._addNodes(e.items),n.start()},update:function(t,e){n._updateNodes(e.items),n.start()},remove:function(t,e){n._removeNodes(e.items),n.start()}},this.edgesListeners={add:function(t,e){n._addEdges(e.items),n.start()},update:function(t,e){n._updateEdges(e.items),n.start()},remove:function(t,e){n._removeEdges(e.items),n.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.stabilize&&this.zoomExtent(!0,this.constants.clustering.enabled),this.constants.clustering.enabled&&this.startWithClustering()}var n=i(45),o=i(41),r=i(46),a=i(1),h=i(42),d=i(3),l=i(4),c=i(38),u=i(39),p=i(34),f=i(35),g=i(36),m=i(33),v=i(37),y=i(44);i(43),n(s.prototype),s.prototype._getScriptPath=function(){for(var t=document.getElementsByTagName("script"),e=0;et.x&&(s=t.x),nt.y&&(e=t.y),i=this.constants.clustering.initialMaxNodes?49.07548/(n+142.05338)+91444e-8:12.662/(n+7.4147)+.0964822:1==this.constants.clustering.enabled&&n>=this.constants.clustering.initialMaxNodes?77.5271985/(n+187.266146)+476710517e-13:30.5062972/(n+19.93597763)+.08413486;var o=Math.min(this.frame.canvas.clientWidth/600,this.frame.canvas.clientHeight/600);i*=o}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=u.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.stabilize){var n=this;setTimeout(function(){n._stabilize(),n.start()},0)}else this.start()},s.prototype.setOptions=function(t){if(t){var e;if(void 0!==t.width&&(this.width=t.width),void 0!==t.height&&(this.height=t.height),void 0!==t.stabilize&&(this.stabilize=t.stabilize),void 0!==t.selectable&&(this.selectable=t.selectable),void 0!==t.freezeForStabilization&&(this.constants.freezeForStabilization=t.freezeForStabilization),void 0!==t.configurePhysics&&(this.constants.configurePhysics=t.configurePhysics),void 0!==t.stabilizationIterations&&(this.constants.stabilizationIterations=t.stabilizationIterations),void 0!==t.dragNetwork&&(this.constants.dragNetwork=t.dragNetwork),void 0!==t.dragNodes&&(this.constants.dragNodes=t.dragNodes),void 0!==t.zoomable&&(this.constants.zoomable=t.zoomable),void 0!==t.hover&&(this.constants.hover=t.hover),void 0!==t.hideEdgesOnDrag&&(this.constants.hideEdgesOnDrag=t.hideEdgesOnDrag),void 0!==t.hideNodesOnDrag&&(this.constants.hideNodesOnDrag=t.hideNodesOnDrag),void 0!==t.dragGraph)throw new Error("Option dragGraph is renamed to dragNetwork");if(void 0!==t.labels)for(e in t.labels)t.labels.hasOwnProperty(e)&&(this.constants.labels[e]=t.labels[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),t.physics){if(t.physics.barnesHut){this.constants.physics.barnesHut.enabled=!0;for(e in t.physics.barnesHut)t.physics.barnesHut.hasOwnProperty(e)&&(this.constants.physics.barnesHut[e]=t.physics.barnesHut[e])}if(t.physics.repulsion){this.constants.physics.barnesHut.enabled=!1;for(e in t.physics.repulsion)t.physics.repulsion.hasOwnProperty(e)&&(this.constants.physics.repulsion[e]=t.physics.repulsion[e])}if(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(void 0!==t.smoothCurves)if("boolean"==typeof t.smoothCurves)this.constants.smoothCurves.enabled=t.smoothCurves;else{this.constants.smoothCurves.enabled=!0;for(e in t.smoothCurves)t.smoothCurves.hasOwnProperty(e)&&(this.constants.smoothCurves[e]=t.smoothCurves[e])}if(t.hierarchicalLayout){this.constants.hierarchicalLayout.enabled=!0;for(e in t.hierarchicalLayout)t.hierarchicalLayout.hasOwnProperty(e)&&(this.constants.hierarchicalLayout[e]=t.hierarchicalLayout[e])}else void 0!==t.hierarchicalLayout&&(this.constants.hierarchicalLayout.enabled=!1);if(t.clustering){this.constants.clustering.enabled=!0;for(e in t.clustering)t.clustering.hasOwnProperty(e)&&(this.constants.clustering[e]=t.clustering[e])}else void 0!==t.clustering&&(this.constants.clustering.enabled=!1);if(t.navigation){this.constants.navigation.enabled=!0;for(e in t.navigation)t.navigation.hasOwnProperty(e)&&(this.constants.navigation[e]=t.navigation[e])}else void 0!==t.navigation&&(this.constants.navigation.enabled=!1);if(t.keyboard){this.constants.keyboard.enabled=!0;for(e in t.keyboard)t.keyboard.hasOwnProperty(e)&&(this.constants.keyboard[e]=t.keyboard[e])}else void 0!==t.keyboard&&(this.constants.keyboard.enabled=!1);if(t.dataManipulation){this.constants.dataManipulation.enabled=!0;for(e in t.dataManipulation)t.dataManipulation.hasOwnProperty(e)&&(this.constants.dataManipulation[e]=t.dataManipulation[e]);this.editMode=this.constants.dataManipulation.initiallyVisible}else void 0!==t.dataManipulation&&(this.constants.dataManipulation.enabled=!1);if(t.edges){for(e in t.edges)t.edges.hasOwnProperty(e)&&"object"!=typeof t.edges[e]&&(this.constants.edges[e]=t.edges[e]);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.edges.dash&&(void 0!==t.edges.dash.length&&(this.constants.edges.dash.length=t.edges.dash.length),void 0!==t.edges.dash.gap&&(this.constants.edges.dash.gap=t.edges.dash.gap),void 0!==t.edges.dash.altLength&&(this.constants.edges.dash.altLength=t.edges.dash.altLength))}if(t.nodes){for(e in t.nodes)t.nodes.hasOwnProperty(e)&&(this.constants.nodes[e]=t.nodes[e]);t.nodes.color&&(this.constants.nodes.color=a.parseColor(t.nodes.color))}if(t.groups)for(var i in t.groups)if(t.groups.hasOwnProperty(i)){var s=t.groups[i];this.groups.add(i,s)}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.width,this.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=o(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],n={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(n)}}},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,n=s.selection;if(n&&n.length&&1==this.constants.dragNodes){var o=e.x-s.pointer.x,r=e.y-s.pointer.y;n.forEach(function(t){var e=t.node;t.xFixed||(e.x=i._XconvertDOMtoCanvas(i._XconvertCanvasToDOM(t.x)+o)),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 n=this._getTranslation(),o=t/i,r=(1-o)*e.x+n.x*o,a=(1-o)*e.y+n.y*o;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 n=h.fakeGesture(this,t),o=this._getPointer(n.center);this._zoom(i,o)}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,n=function(){s._checkShowPopup(i)};if(this.popupTimer&&clearInterval(this.popupTimer),this.drag.dragging||(this.popupTimer=setTimeout(n,this.constants.tooltip.delay)),1==this.constants.hover){for(var o in this.hoverObj.edges)this.hoverObj.edges.hasOwnProperty(o)&&(this.hoverObj.edges[o].hover=!1,delete this.hoverObj.edges[o]);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 g&&r.id!=a||r instanceof m||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 n=this.nodes;for(e in n)if(n.hasOwnProperty(e)){var o=n[e];if(void 0!==o.getTitle()&&o.isOverlappingWith(i)){this.popupObj=o;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 n=this.nodesData.get(e),o=new g(n,this.images,this.groups,this.constants);if(this.nodes[e]=o,!(0!=o.xFixed&&0!=o.yFixed||null!==o.x&&null!==o.y)){var r=1*t.length,a=2*Math.PI*Math.random();0==o.xFixed&&(o.x=r*Math.cos(a)),0==o.yFixed&&(o.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,n=t.length;n>s;s++){var o=t[s],r=e[o],a=i.get(o);r?r.setProperties(a,this.constants):(r=new g(properties,this.images,this.groups,this.constants),e[o]=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 n=t[i];delete e[n]}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,n=t.length;n>s;s++){var o=t[s],r=e[o];r&&r.disconnect();var a=i.get(o,{showInternalIds:!0});e[o]=new m(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,n=t.length;n>s;s++){var o=t[s],r=i.get(o),a=e[o];a?(a.disconnect(),a.setProperties(r,this.constants),a.connect()):(a=new m(r,this,this.constants),this.edges[o]=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 n=t[i],o=e[n];o&&(null!=o.via&&delete this.sectors.support.nodes[o.via.id],o.disconnect(),delete e[n])}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 n=t[e].getValue();void 0!==n&&(i=void 0===i?n:Math.min(n,i),s=void 0===s?n:Math.max(n,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.width,this.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 n in i)i.hasOwnProperty(n)&&(i[n].setScaleAndPos(this.scale,this.canvasTopLeft,this.canvasBottomRight),i[n].isSelected()?s.push(n):(i[n].inArea()||e)&&i[n].draw(t));for(var o=0,r=s.length;r>o;o++)(i[s[o]].inArea()||e)&&i[s[o]].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 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"),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.color;return"to"==this.inheritColor?t={highlight:this.to.color.highlight.border,hover:this.to.color.hover.border,color:this.to.color.border}:("from"==this.inheritColor||1==this.inheritColor)&&(t={highlight:this.from.color.highlight.border,hover:this.from.color.hover.border,color:this.from.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.smoothCurves.enabled&&null!=i){var s=.5*(.5*(this.from.x+i.x)+.5*(this.to.x+i.x)),n=.5*(.5*(this.from.y+i.y)+.5*(this.to.y+i.y));e={x:s,y:n}}else e=this._pointOnLine(.5);this._label(t,this.label,e.x,e.y)}}else{var o,r,a=this.length/4,h=this.from;h.width||h.resize(t),h.width>h.height?(o=h.x+h.width/2,r=h.y-a):(o=h.x+a,r=h.y-h.height/2),this._circle(t,o,r,a),e=this._pointOnCircle(o,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.widthMax)*this.networkScaleInv:1==this.hover?Math.min(this.hoverWidth,this.widthMax)*this.networkScaleInv:this.width*this.networkScaleInv},s.prototype._getViaCoordinates=function(){var t=null,e=null,i=this.smoothCurves.roundness,s=this.smoothCurves.type,n=Math.abs(this.from.x-this.to.x),o=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*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&&(t=i*o>n?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*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&&(e=i*n>o?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*o,e=this.from.y-i*o,t=this.to.x>t?this.to.x:t):this.from.ythis.to.x&&(t=this.from.x-i*o,e=this.from.y+i*o,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*n,e=this.from.y-i*n,e=this.to.y>e?this.to.y:e):this.from.ythis.to.x&&(t=this.from.x-i*n,e=this.from.y+i*n,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,n=(10+5*this.width)*this.arrowScaleFactor;e=this._pointOnCircle(a,h,d,.5),t.arrow(e.x,e.y,s,n),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.color.highlight,t.fillStyle=this.color.highlight):1==this.hover?(t.strokeStyle=this.color.hover,t.fillStyle=this.color.hover):(t.strokeStyle=this.color.color,t.fillStyle=this.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,n=this.to.x-this.from.x,o=this.to.y-this.from.y,r=Math.sqrt(n*n+o*o),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.smoothCurves.dynamic&&1==this.smoothCurves.enabled?s=this.via:1==this.smoothCurves.enabled&&(s=this._getViaCoordinates()),1==this.smoothCurves.enabled&&null!=s.x&&(e=Math.atan2(this.to.y-s.y,this.to.x-s.x),n=this.to.x-s.x,o=this.to.y-s.y,r=Math.sqrt(n*n+o*o));var c,u,p=this.to.distanceToBorder(t,e),f=(r-p)/r;if(1==this.smoothCurves.enabled&&null!=s.x?(c=(1-f)*s.x+f*this.to.x,u=(1-f)*s.y+f*this.to.y):(c=(1-f)*this.from.x+f*this.to.x,u=(1-f)*this.from.y+f*this.to.y),t.beginPath(),t.moveTo(d,l),1==this.smoothCurves.enabled&&null!=s.x?t.quadraticCurveTo(s.x,s.y,c,u):t.lineTo(c,u),t.stroke(),i=(10+5*this.width)*this.arrowScaleFactor,t.arrow(c,u,e,i),t.fill(),t.stroke(),this.label){var g;if(1==this.smoothCurves.enabled&&null!=s){var m=.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));g={x:m,y:v}}else g=this._pointOnLine(.5);this._label(t,this.label,g.x,g.y)}}else{var y,b,_,x=this.from,w=.25*Math.max(100,this.length);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.width)*this.arrowScaleFactor;t.arrow(_.x,_.y,_.angle,i),t.fill(),t.stroke(),this.label&&(g=this._pointOnCircle(y,b,w,.5),this._label(t,this.label,g.x,g.y))}},s.prototype._getDistanceToEdge=function(t,e,i,s,n,o){if(this.from!=this.to){if(1==this.smoothCurves.enabled){var r,a;if(1==this.smoothCurves.enabled&&1==this.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,u,p,f,g,m=1e9;for(l=0;10>l;l++)c=.1*l,u=Math.pow(1-c,2)*t+2*c*(1-c)*r+Math.pow(c,2)*i,p=Math.pow(1-c,2)*e+2*c*(1-c)*a+Math.pow(c,2)*s,l>0&&(d=this._getDistanceToLine(f,g,u,p,n,o),m=m>d?d:m),f=u,g=p;return m}return this._getDistanceToLine(t,e,i,s,n,o)}var u,p,v,y,b=this.length/4,_=this.from;return _.width||_.resize(ctx),_.width>_.height?(u=_.x+_.width/2,p=_.y-b):(u=_.x+b,p=_.y-_.height/2),v=u-n,y=p-o,Math.abs(Math.sqrt(v*v+y*y)-b)},s.prototype._getDistanceToLine=function(t,e,i,s,n,o){var r=i-t,a=s-e,h=r*r+a*a,d=((n-t)*r+(o-e)*a)/h;d>1?d=1:0>d&&(d=0);var l=t+d*r,c=e+d*a,u=l-n,p=c-o;return Math.sqrt(u*u+p*p)},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&&(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 o({id:e,shape:"dot",color:{background:"#ff4e00",border:"#3c3c3c",highlight:{background:"#07f968"}}},{},{},s),this.controlNodes.to=new o({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)),n=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>n?(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,n=this.to.y-this.from.y,o=Math.sqrt(s*s+n*n),r=this.from.distanceToBorder(t,i+Math.PI),a=(o-r)/o,h=a*this.from.x+(1-a)*this.to.x,d=a*this.from.y+(1-a)*this.to.y;1==this.smoothCurves.dynamic&&1==this.smoothCurves.enabled?e=this.via:1==this.smoothCurves.enabled&&(e=this._getViaCoordinates()),1==this.smoothCurves.enabled&&null!=e.x&&(i=Math.atan2(this.to.y-e.y,this.to.x-e.x),s=this.to.x-e.x,n=this.to.y-e.y,o=Math.sqrt(s*s+n*n));var l,c,u=this.to.distanceToBorder(t,i),p=(o-u)/o;return 1==this.smoothCurves.enabled&&null!=e.x?(l=(1-p)*e.x+p*this.to.x,c=(1-p)*e.y+p*this.to.y):(l=(1-p)*this.from.x+p*this.to.x,c=(1-p)*this.from.y+p*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 n=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=n.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){this.selected=!1,this.hover=!1,this.edges=[],this.dynamicEdges=[],this.reroutedEdges={},this.group=s.nodes.group,this.fontSize=Number(s.nodes.fontSize),this.fontFace=s.nodes.fontFace,this.fontColor=s.nodes.fontColor,this.fontDrawThreshold=3,this.color=s.nodes.color,this.id=void 0,this.shape=s.nodes.shape,this.image=s.nodes.image,this.x=null,this.y=null,this.xFixed=!1,this.yFixed=!1,this.horizontalAlignLeft=!0,this.verticalAlignTop=!0,this.radius=s.nodes.radius,this.baseRadiusValue=s.nodes.radius,this.radiusFixed=!1,this.radiusMin=s.nodes.radiusMin,this.radiusMax=s.nodes.radiusMax,this.level=-1,this.preassignedLevel=!1,this.borderWidth=s.nodes.borderWidth,this.borderWidthSelected=s.nodes.borderWidthSelected,this.imagelist=e,this.grouplist=i,this.fx=0,this.fy=0,this.vx=0,this.vy=0,this.minForce=s.minForce,this.damping=s.physics.damping,this.mass=1,this.fixedData={x:null,y:null},this.setProperties(t,s),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 n=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){if(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.group&&(this.group=t.group),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.borderWidth&&(this.borderWidth=t.borderWidth),void 0!==t.borderWidthSelected&&(this.borderWidthSelected=t.borderWidthSelected),void 0!==t.mass&&(this.mass=t.mass),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(void 0!==this.group&&""!=this.group){var i=this.grouplist.get(this.group);for(var s in i)i.hasOwnProperty(s)&&(this[s]=i[s])}if(void 0!==t.shape&&(this.shape=t.shape),void 0!==t.image&&(this.image=t.image),void 0!==t.radius&&(this.radius=t.radius,this.baseRadiusValue=this.radius),void 0!==t.color&&(this.color=n.parseColor(t.color)),void 0!==t.fontColor&&(this.fontColor=t.fontColor),void 0!==t.fontSize&&(this.fontSize=t.fontSize),void 0!==t.fontFace&&(this.fontFace=t.fontFace),void 0!==this.image&&""!=this.image){if(!this.imagelist)throw"No imagelist provided";this.imageObj=this.imagelist.load(this.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.shape&&(this.radiusMin=e.nodes.widthMin,this.radiusMax=e.nodes.widthMax),this.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.shape){case"circle":case"dot":return this.radius+i;case"ellipse":var s=this.width/2,n=this.height/2,o=Math.sin(e)*s,r=Math.cos(e)*n;return s*n/Math.sqrt(o*o+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.mass;this.vx+=i*t,this.x+=this.vx*t}if(!this.yFixed){var s=this.damping*this.vy,n=(this.fy-s)/this.mass;this.vy+=n*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.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 n=this.damping*this.vy,o=(this.fy-n)/this.mass;this.vy+=o*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.radius=(this.radiusMin+this.radiusMax)/2;else{var i=(this.radiusMax-this.radiusMin)/(e-t);this.radius=(this.value-t)*i+this.radiusMin}this.baseRadiusValue=this.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.radius=this.baseRadiusValue;var i=this.imageObj.height/this.imageObj.width;void 0!==i?(t=this.radius||this.imageObj.width,e=this.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.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.borderWidth,s=this.borderWidthSelected||2*this.borderWidth;t.strokeStyle=this.selected?this.color.highlight.border:this.hover?this.color.hover.border:this.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.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.color.highlight.background:this.color.background,t.roundRect(this.left,this.top,this.width,this.height,this.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.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.borderWidth,s=this.borderWidthSelected||2*this.borderWidth;t.strokeStyle=this.selected?this.color.highlight.border:this.hover?this.color.hover.border:this.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.color.highlight.background:this.hover?this.color.hover.background:this.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.radius=s/2,this.width=s,this.height=s,this.radius+=.5*Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeRadiusFactor,this.growthIndicator=this.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.borderWidth,s=this.borderWidthSelected||2*this.borderWidth;t.strokeStyle=this.selected?this.color.highlight.border:this.hover?this.color.hover.border:this.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.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.color.highlight.background:this.hover?this.color.hover.background:this.color.background,t.circle(this.x,this.y,this.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.color.highlight.background:this.hover?this.color.hover.background:this.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.radius=this.baseRadiusValue;var t=2*this.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.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.borderWidth,n=this.borderWidthSelected||2*this.borderWidth,o=2;switch(e){case"dot":o=2;break;case"square":o=2;break;case"triangle":o=3;break;case"triangleDown":o=3;break;case"star":o=4}t.strokeStyle=this.selected?this.color.highlight.border:this.hover?this.color.hover.border:this.color.border,this.clusterSize>1&&(t.lineWidth=(this.selected?n: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.radius+o*t.lineWidth),t.stroke()),t.lineWidth=(this.selected?n:s)+(this.clusterSize>1?i:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.fillStyle=this.selected?this.color.highlight.background:this.hover?this.color.hover.background:this.color.background,t[e](this.x,this.y,this.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.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,n,o,r){if(e&&this.fontSize*this.networkScale>this.fontDrawThreshold){t.font=(this.selected?"bold ":"")+this.fontSize+"px "+this.fontFace,t.fillStyle=this.fontColor||"black",t.textAlign=n||"center",t.textBaseline=o||"middle";var a=e.split("\n"),h=a.length,d=this.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.fontSize+"px "+this.fontFace;for(var e=this.label.split("\n"),i=(this.fontSize+4)*e.length,s=0,n=0,o=e.length;o>n;n++)s=Math.max(s,t.measureText(e[n]).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&&(o=s-e-this.padding),on&&(r=n-i-this.padding),ri;i++)if(e.id===r.nodes[i].id){n=r.nodes[i];break}for(n||(n={id:e.id},t.node&&(n.attr=a(n.attr,t.node))),i=o.length-1;i>=0;i--){var h=o[i];h.nodes||(h.nodes=[]),-1==h.nodes.indexOf(n)&&h.nodes.push(n)}e.attr&&(n.attr=a(n.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,n){var o={from:e,to:i,type:s};return t.edge&&(o.attr=a({},t.edge)),o.attr=a(o.attr||{},n),o}function u(){for(N=D.NULL,O="";" "==L||" "==L||"\n"==L||"\r"==L;)n();do{var t=!1;if("#"==L){for(var e=T-1;" "==C.charAt(e)||" "==C.charAt(e);)e--;if("\n"==C.charAt(e)||""==C.charAt(e)){for(;""!=L&&"\n"!=L;)n();t=!0}}if("/"==L&&"/"==o()){for(;""!=L&&"\n"!=L;)n();t=!0}if("/"==L&&"*"==o()){for(;""!=L;){if("*"==L&&"/"==o()){n(),n();break}n()}t=!0}for(;" "==L||" "==L||"\n"==L||"\r"==L;)n()}while(t);if(""==L)return void(N=D.DELIMITER);var i=L+o();if(E[i])return N=D.DELIMITER,O=i,n(),void n();if(E[L])return N=D.DELIMITER,O=L,void n();if(r(L)||"-"==L){for(O+=L,n();r(L);)O+=L,n();return"false"==O?O=!1:"true"==O?O=!0:isNaN(Number(O))||(O=Number(O)),void(N=D.IDENTIFIER)}if('"'==L){for(n();""!=L&&('"'!=L||'"'==L&&'"'==o());)O+=L,'"'==L&&n(),n();if('"'!=L)throw x('End of string " expected');return n(),void(N=D.IDENTIFIER)}for(N=D.UNKNOWN;""!=L;)O+=L,n();throw new SyntaxError('Syntax error in part "'+w(O,30)+'"')}function p(){var t={};if(s(),u(),"strict"==O&&(t.strict=!0,u()),("graph"==O||"digraph"==O)&&(t.type=O,u()),N==D.IDENTIFIER&&(t.id=O,u()),"{"!=O)throw x("Angle bracket { expected");if(u(),f(t),"}"!=O)throw x("Angle bracket } expected");if(u(),""!==O)throw x("End of file expected");return u(),delete t.node,delete t.edge,delete t.graph,t}function f(t){for(;""!==O&&"}"!=O;)g(t),";"==O&&u()}function g(t){var e=m(t);if(e)return void b(t,e);var i=v(t);if(!i){if(N!=D.IDENTIFIER)throw x("Identifier expected");var s=O;if(u(),"="==O){if(u(),N!=D.IDENTIFIER)throw x("Identifier expected");t[s]=O,u()}else y(t,s)}}function m(t){var e=null;if("subgraph"==O&&(e={},e.type="subgraph",u(),N==D.IDENTIFIER&&(e.id=O,u())),"{"==O){if(u(),e||(e={}),e.parent=t,e.node=t.node,e.edge=t.edge,e.graph=t.graph,f(e),"}"!=O)throw x("Angle bracket } expected");u(),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"==O?(u(),t.node=_(),"node"):"edge"==O?(u(),t.edge=_(),"edge"):"graph"==O?(u(),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(;"->"==O||"--"==O;){var i,s=O;u();var n=m(t);if(n)i=n;else{if(N!=D.IDENTIFIER)throw x("Identifier or subgraph expected");i=O,d(t,{id:i}),u()}var o=_(),r=c(t,e,i,s,o);l(t,r),e=i}}function _(){for(var t=null;"["==O;){for(u(),t={};""!==O&&"]"!=O;){if(N!=D.IDENTIFIER)throw x("Attribute name expected");var e=O;if(u(),"="!=O)throw x("Equal sign = expected");if(u(),N!=D.IDENTIFIER)throw x("Attribute value expected");var i=O;h(t,e,i),u(),","==O&&u()}if("]"!=O)throw x("Bracket ] expected");u()}return t}function x(t){return new SyntaxError(t+', got "'+w(O,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),n={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"),n.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);n.edges.push(i)}),S(i,s,function(i,s){var o=c(n,i.id,s.id,t.type,t.attr),r=e(o);n.edges.push(r)}),t.to instanceof Object&&t.to.edges&&t.to.edges.forEach(function(t){var i=e(t);n.edges.push(i)})}),s.attr&&(n.options=s.attr),n}var D={NULL:0,DELIMITER:1,IDENTIFIER:2,UNKNOWN:3},E={"{":!0,"}":!0,"[":!0,"]":!0,";":!0,"=":!0,",":!0,"->":!0,"--":!0},C="",T=0,L="",O="",N=D.NULL,k=/[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 n=t.edges,o=t.nodes,r=0;rs;s++){var n=s%2===0?1.3*i:.5*i;this.lineTo(t+n*Math.sin(2*s*Math.PI/10),e-n*Math.cos(2*s*Math.PI/10))}this.closePath()},CanvasRenderingContext2D.prototype.roundRect=function(t,e,i,s,n){var o=Math.PI/180;0>i-2*n&&(n=i/2),0>s-2*n&&(n=s/2),this.beginPath(),this.moveTo(t+n,e),this.lineTo(t+i-n,e),this.arc(t+i-n,e+n,n,270*o,360*o,!1),this.lineTo(t+i,e+s-n),this.arc(t+i-n,e+s-n,n,0,90*o,!1),this.lineTo(t+n,e+s),this.arc(t+n,e+s-n,n,90*o,180*o,!1),this.lineTo(t,e+n),this.arc(t+n,e+n,n,180*o,270*o,!1)},CanvasRenderingContext2D.prototype.ellipse=function(t,e,i,s){var n=.5522848,o=i/2*n,r=s/2*n,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-o,e,d,e),this.bezierCurveTo(d+o,e,a,l-r,a,l),this.bezierCurveTo(a,l+r,d+o,h,d,h),this.bezierCurveTo(d-o,h,t,l+r,t,l)},CanvasRenderingContext2D.prototype.database=function(t,e,i,s){var n=1/3,o=i,r=s*n,a=.5522848,h=o/2*a,d=r/2*a,l=t+o,c=e+r,u=t+o/2,p=e+r/2,f=e+(s-r/2),g=e+s;this.beginPath(),this.moveTo(l,p),this.bezierCurveTo(l,p+d,u+h,c,u,c),this.bezierCurveTo(u-h,c,t,p+d,t,p),this.bezierCurveTo(t,p-d,u-h,e,u,e),this.bezierCurveTo(u+h,e,l,p-d,l,p),this.lineTo(l,f),this.bezierCurveTo(l,f+d,u+h,g,u,g),this.bezierCurveTo(u-h,g,t,f+d,t,f),this.lineTo(t,p)},CanvasRenderingContext2D.prototype.arrow=function(t,e,i,s){var n=t-s*Math.cos(i),o=e-s*Math.sin(i),r=t-.9*s*Math.cos(i),a=e-.9*s*Math.sin(i),h=n+s/3*Math.cos(i+.5*Math.PI),d=o+s/3*Math.sin(i+.5*Math.PI),l=n+s/3*Math.cos(i-.5*Math.PI),c=o+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,n){n||(n=[10,5]),0==u&&(u=.001);var o=n.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 u=n[l++%o];u>d&&(u=d);var p=Math.sqrt(u*u/(1+h*h));0>r&&(p=-p),t+=p,e+=h*p,this[c?"lineTo":"moveTo"](t,e),d-=u,c=!c}})},function(t,e,i){var s=i(55),n=i(49),o=i(50),r=i(51),a=i(52),h=i(53),d=i(54);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(n)},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(o)},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,n=0;ns;++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 n(t,e){return t.sort().join(",")===e.sort().join(",")}function o(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,o){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=p()[t]?"keydown":"keypress"),"keypress"==i&&e.length&&(i="keydown"),i}function g(t,e,s,n){E[t]=0,n||(n=f(e[0],[]));var r,a=function(){T=n,++E[t],u()},d=function(t){h(s,t),"keyup"!==n&&(C=i(t)),setTimeout(o,10)};for(r=0;r1)return g(t,d,e,i);for(h="+"===t?["+"]:t.split("+"),o=0;o":".","?":"/","|":"\\"},S={option:"alt",command:"meta","return":"enter",escape:"esc"},M={},D={},E={},C=!1,T=!1,L=1;20>L;++L)_[111+L]="f"+L;for(L=0;9>=L;++L)_[L+96]=L;e(document,"keypress",l),e(document,"keydown",l),e(document,"keyup",l);var O={bind:function(t,e,i){return v(t instanceof Array?t:[t],e,i),D[t+":"+i]=e,this},unbind:function(t,e){return D[t+":"+e]&&(delete D[t+":"+e],this.bind(t,function(){},e)),this},trigger:function(t,e){return D[t+":"+e](),this},reset:function(){return M={},D={},this}};t.exports=O},function(t,e,i){var s;(function(t,n){(function(o){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 u(t){O(t),f(this,t)}function p(t){var e=S(t),i=e.year||0,s=e.quarter||0,n=e.month||0,o=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*o,this._months=+n+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 g(t){var e,i={};for(e in t)t.hasOwnProperty(e)&&Ne.hasOwnProperty(e)&&(i[e]=t[e]);return i}function m(t){return 0>t?Math.ceil(t):Math.floor(t)}function v(t,e,i){for(var s=""+Math.abs(t),n=t>=0;s.lengths;s++)(i&&t[s]!==e[s]||!i&&D(t[s])!==D(e[s]))&&r++;return r+o}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,n){var r,a,h=ve.fn._lang[t],d=[];if("number"==typeof s&&(n=s,s=o),a=function(t){var e=ve().utc().set(i,t);return h.call(ve.fn._lang,e,s||"")},null!=n)return a(n);for(r=0;e>r;r++)d.push(a(r));return d}}function D(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 C(t,e,i){return re(ve([t,11,31+e-i]),e,i).week}function T(t){return L(t)?366:365}function L(t){return t%4===0&&t%100!==0||t%400===0}function O(t){var e;t._a&&-2===t._pf.overflow&&(e=t._a[Me]<0||t._a[Me]>11?Me:t._a[De]<1||t._a[De]>E(t._a[Se],t._a[Me])?De:t._a[Ee]<0||t._a[Ee]>23?Ee:t._a[Ce]<0||t._a[Ce]>59?Ce:t._a[Te]<0||t._a[Te]>59?Te:t._a[Le]<0||t._a[Le]>999?Le:-1,t._pf._overflowDayOfYear&&(Se>e||e>De)&&(e=De),t._pf.overflow=e)}function N(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 k(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,Oe[t]||(Oe[t]=new c),Oe[t].set(e),Oe[t]}function z(t){delete Oe[t]}function P(t){var e,s,n,o,r=0,a=function(t){if(!Oe[t]&&ke)try{i(56)("./"+t)}catch(e){}return Oe[t]};if(!t)return ve.fn._lang;if(!b(t)){if(s=a(t))return s;t=[t]}for(;r0;){if(s=a(o.slice(0,e).join("-")))return s;if(n&&n.length>=e&&x(o,n,!0)>=e-1)break;e--}r++}return ve.fn._lang}function F(t){return t.match(/\[[\s\S]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"")}function R(t){var e,i,s=t.match(Pe);for(e=0,i=s.length;i>e;e++)s[e]=ui[s[e]]?ui[s[e]]:F(s[e]);return function(n){var o="";for(e=0;i>e;e++)o+=s[e]instanceof Function?s[e].call(n,t):s[e];return o}}function H(t,e){return t.isValid()?(e=Y(e,t.lang()),hi[e]||(hi[e]=R(e)),hi[e](t)):t.lang().invalidDate()}function Y(t,e){function i(t){return e.longDateFormat(t)||t}var s=5;for(Fe.lastIndex=0;s>=0&&Fe.test(t);)t=t.replace(Fe,i),Fe.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 Ve;case"Z":case"ZZ":return je;case"T":return Ue;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:Re;case"M":case"D":case"d":case"H":case"h":case"m":case"s":case"w":case"W":case"e":case"E":return Re;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(ni)||["-",0,0],n=+(60*s[1])+D(s[2]);return"+"===s[0]?-n:n}function G(t,e,i){var s,n=i._a;switch(t){case"Q":null!=e&&(n[Me]=3*(D(e)-1));break;case"M":case"MM":null!=e&&(n[Me]=D(e)-1);break;case"MMM":case"MMMM":s=P(i._l).monthsParse(e),null!=s?n[Me]=s:i._pf.invalidMonth=e;break;case"D":case"DD":null!=e&&(n[De]=D(e));break;case"Do":null!=e&&(n[De]=D(parseInt(e,10)));break;case"DDD":case"DDDD":null!=e&&(i._dayOfYear=D(e));break;case"YY":n[Se]=ve.parseTwoDigitYear(e);break;case"YYYY":case"YYYYY":case"YYYYYY":n[Se]=D(e);break;case"a":case"A":i._isPm=P(i._l).isPM(e);break;case"H":case"HH":case"h":case"hh":n[Ee]=D(e);break;case"m":case"mm":n[Ce]=D(e);break;case"s":case"ss":n[Te]=D(e);break;case"S":case"SS":case"SSS":case"SSSS":n[Le]=D(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]=D(e));break;case"gg":case"GG":i._w=i._w||{},i._w[t]=ve.parseTwoDigitYear(e)}}function j(t){var e,i,s,n,o,a,h,d;e=t._w,null!=e.GG||null!=e.W||null!=e.E?(o=1,a=4,i=r(e.GG,t._a[Se],re(ve(),1,4).year),s=r(e.W,1),n=r(e.E,1)):(d=P(t._l),o=d._week.dow,a=d._week.doy,i=r(e.gg,t._a[Se],re(ve(),o,a).year),s=r(e.w,1),null!=e.d?(n=e.d,o>n&&++s):n=null!=e.e?e.e+o:o),h=ae(i,s,n,a,o),t._a[Se]=h.year,t._dayOfYear=h.dayOfYear}function U(t){var e,i,s,n,o=[];if(!t._d){for(s=X(t),t._w&&null==t._a[De]&&null==t._a[Me]&&j(t),t._dayOfYear&&(n=r(t._a[Se],s[Se]),t._dayOfYear>T(n)&&(t._pf._overflowDayOfYear=!0),i=ie(n,0,t._dayOfYear),t._a[Me]=i.getUTCMonth(),t._a[De]=i.getUTCDate()),e=0;3>e&&null==t._a[e];++e)t._a[e]=o[e]=s[e];for(;7>e;e++)t._a[e]=o[e]=null==t._a[e]?2===e?1:0:t._a[e];t._d=(t._useUTC?ie:ee).apply(null,o),null!=t._tzm&&t._d.setUTCMinutes(t._d.getUTCMinutes()+t._tzm)}}function V(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],U(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,n,o,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(o),a=a.slice(a.indexOf(i)+i.length),d+=i.length),ui[n]?(i?t._pf.empty=!1:t._pf.unusedTokens.push(n),G(n,i,t)):t._strict&&!i&&t._pf.unusedTokens.push(n);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),U(t),O(t)}function q(t){return t.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(t,e,i,s,n){return e||i||s||n})}function K(t){return t.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function $(t){var e,i,s,n,o;if(0===t._f.length)return t._pf.invalidFormat=!0,void(t._d=new Date(0/0));for(n=0;no)&&(s=o,i=e));f(t,i||e)}function J(t){var e,i,s=t._i,n=ti.exec(s);if(n){for(t._pf.iso=!0,e=0,i=ii.length;i>e;e++)if(ii[e][1].exec(s)){t._f=ii[e][0]+(n[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===o?t._d=new Date:i?t._d=new Date(+i[1]):"string"==typeof e?Q(t):b(e)?(t._a=e.slice(0),U(t)):_(e)?t._d=new Date(+e):"object"==typeof e?V(t):"number"==typeof e?t._d=new Date(e):ve.createFromInputFallback(t)}function ee(t,e,i,s,n,o,r){var a=new Date(t,e,i,s,n,o,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 ne(t,e,i,s,n){return n.relativeTime(e||1,!!i,t,s)}function oe(t,e,i){var s=we(Math.abs(t)/1e3),n=we(s/60),o=we(n/60),r=we(o/24),a=we(r/365),h=s0,h[4]=i,ne.apply({},h)}function re(t,e,i){var s,n=i-e,o=i-t.day();return o>n&&(o-=7),n-7>o&&(o+=7),s=ve(t).add("d",o),{week:Math.ceil(s.dayOfYear()/7),year:s.year()}}function ae(t,e,i,s,n){var o,r,a=ie(t,0,1).getUTCDay();return a=0===a?7:a,i=null!=i?i:n,o=n-a+(a>s?7:0)-(n>a?7:0),r=7*(e-1)+(i-n)+o+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===o&&""===e?ve.invalid({nullInput:!0}):("string"==typeof e&&(t._i=e=P().preparse(e)),ve.isMoment(e)?(t=g(e),t._d=new Date(+e._d)):i?b(i)?$(t):Z(t):te(t),new u(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 D(this.milliseconds()/100)},SS:function(){return v(D(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(D(t/60),2)+":"+v(D(t)%60,2)},ZZ:function(){var t=-this.zone(),e="+";return 0>t&&(t=-t,e="-"),e+v(D(t/60),2)+v(D(t)%60,2)},z:function(){return this.zoneAbbr()},zz:function(){return this.zoneName()},X:function(){return this.unix()},Q:function(){return this.quarter()}},pi=["months","monthsShort","weekdays","weekdaysShort","weekdaysMin"];li.length;)be=li.pop(),ui[be+"o"]=l(ui[be],be);for(;ci.length;)be=ci.pop(),ui[be+be]=d(ui[be],2);for(ui.DDDD=d(ui.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 n=this._relativeTime[i];return"function"==typeof n?n(t,e,i,s):n.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 n;return"boolean"==typeof i&&(s=i,i=o),n={},n._isAMomentObject=!0,n._i=t,n._f=e,n._l=i,n._strict=s,n._isUTC=!1,n._pf=a(),he(n)},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 n;return"boolean"==typeof i&&(s=i,i=o),n={},n._isAMomentObject=!0,n._useUTC=!0,n._isUTC=!0,n._l=i,n._i=t,n._f=e,n._strict=s,n._pf=a(),he(n).utc()},ve.unix=function(t){return ve(1e3*t)},ve.duration=function(t,e){var i,s,n,o=t,r=null;return ve.isDuration(t)?o={ms:t._milliseconds,d:t._days,M:t._months}:"number"==typeof t?(o={},e?o[e]=t:o.milliseconds=t):(r=Ae.exec(t))?(i="-"===r[1]?-1:1,o={y:0,d:D(r[De])*i,h:D(r[Ee])*i,m:D(r[Ce])*i,s:D(r[Te])*i,ms:D(r[Le])*i}):(r=ze.exec(t))&&(i="-"===r[1]?-1:1,n=function(t){var e=t&&parseFloat(t.replace(",","."));return(isNaN(e)?0:e)*i},o={y:n(r[2]),M:n(r[3]),d:n(r[4]),h:n(r[5]),m:n(r[6]),s:n(r[7]),w:n(r[8])}),s=new p(o),ve.isDuration(t)&&t.hasOwnProperty("_lang")&&(s._lang=t._lang),s},ve.version=_e,ve.defaultFormat=ei,ve.ISO_8601=function(){},ve.momentProperties=Ne,ve.updateOffset=function(){},ve.relativeTimeThreshold=function(t,e){return di[t]===o?!1:(di[t]=e,!0)},ve.lang=function(t,e){var i;return t?(e?A(k(t),e):null===e?(z(t),t="en"):Oe[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 u||null!=t&&t.hasOwnProperty("_isAMomentObject")},ve.isDuration=function(t){return t instanceof p},be=pi.length-1;be>=0;--be)M(pi[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 D(t)+(D(t)>68?1900:2e3)},f(ve.fn=u.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,n,o=I(t,this),r=6e4*(this.zone()-o.zone());return e=w(e),"year"===e||"month"===e?(s=432e5*(this.daysInMonth()+o.daysInMonth()),n=12*(this.year()-o.year())+(this.month()-o.month()),n+=(this-ve(this).startOf("month")-(o-ve(o).startOf("month")))/s,n-=6e4*(this.zone()-ve(this).startOf("month").zone()-(o.zone()-ve(o).startOf("month").zone()))/s,"year"===e&&(n/=12)):(s=this-o,n="second"===e?s/1e3:"minute"===e?s/6e4:"hour"===e?s/36e5:"day"===e?(s-r)/864e5:"week"===e?(s-r)/6048e5:s),i?n:m(n)},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),n=-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(n,this))},isLeapYear:function(){return L(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 C(this.year(),1,4)},weeksInYear:function(){var t=this._lang._week;return C(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===o?this._lang:(this._lang=P(t),this)}}),ve.fn.millisecond=ve.fn.milliseconds=pe("Milliseconds",!1),ve.fn.second=ve.fn.seconds=pe("Seconds",!1),ve.fn.minute=ve.fn.minutes=pe("Minutes",!1),ve.fn.hour=ve.fn.hours=pe("Hours",!0),ve.fn.date=pe("Date",!0),ve.fn.dates=h("dates accessor is deprecated. Use date instead.",pe("Date",!0)),ve.fn.year=pe("FullYear",!0),ve.fn.years=h("years accessor is deprecated. Use year instead.",pe("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=p.prototype,{_bubble:function(){var t,e,i,s,n=this._milliseconds,o=this._days,r=this._months,a=this._data;a.milliseconds=n%1e3,t=m(n/1e3),a.seconds=t%60,e=m(t/60),a.minutes=e%60,i=m(e/60),a.hours=i%24,o+=m(i/24),a.days=o%30,r+=m(o/30),a.months=r%12,s=m(r/12),a.years=s},weeks:function(){return m(this.days()/7)},valueOf:function(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*D(this._months/12)},humanize:function(t){var e=+this,i=oe(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()),n=Math.abs(this.minutes()),o=Math.abs(this.seconds()+this.milliseconds()/1e3);return this.asSeconds()?(this.asSeconds()<0?"-":"")+"P"+(t?t+"Y":"")+(e?e+"M":"")+(i?i+"D":"")+(s||n||o?"T":"")+(s?s+"H":"")+(n?n+"M":"")+(o?o+"S":""):"P0D"}});for(be in oi)oi.hasOwnProperty(be)&&(ge(be,oi[be]),fe(be.toLowerCase()));ge("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===D(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th";return t+i}}),ke?n.exports=ve:(s=function(t,e,i){return i.config&&i.config()&&i.config().noGlobal===!0&&(xe.moment=ye),ve}.call(e,i,e,n),!(s!==o&&(n.exports=s)),me(!0))}).call(this)}).call(e,function(){return this}(),i(60)(t))},function(t,e,i){var s;!function(n,o){"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 D(t,e){return new D.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 n,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",u=a.DIRECTION_RIGHT="right",p=a.POINTER_MOUSE="mouse",f=a.POINTER_TOUCH="touch",g=a.POINTER_PEN="pen",m=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]!==o&&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,n;if("forEach"in t)t.forEach(e,i);else if(t.length!==o){for(s=0,n=t.length;n>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,n=t.length;n>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=[],n=[],o=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),n.push(t.clientY)}),{pageX:(o.apply(Math,e)+r.apply(Math,e))/2,pageY:(o.apply(Math,i)+r.apply(Math,i))/2,clientX:(o.apply(Math,s)+r.apply(Math,s))/2,clientY:(o.apply(Math,n)+r.apply(Math,n))/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:u: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 n=["","Webkit","Moz","O","ms"];e=x.toCamelCase(e);for(var o=0;o0&&this.started&&(r=v),this.started=!0;var d=this.collectEventData(i,r,n,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?n.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[m]=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)),n=[];return x.each(s,function(t){x.inArray(i,t.identifier)===!1&&n.push(t),i.push(t.identifier)}),n}return t.identifier=1,[t]},collectEventData:function(t,e,i,s){var n=f;return x.inStr(s.type,"mouse")||S.matchType(p,s)?n=p:S.matchType(g,s)&&(n=g),{center:x.getCenter(i),timeStamp:Date.now(),target:s.target,touches:i,eventType:e,pointerType:n,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[p]=i===(e.MSPOINTER_TYPE_MOUSE||p),s[f]=i===(e.MSPOINTER_TYPE_TOUCH||f),s[g]=i===(e.MSPOINTER_TYPE_PEN||g),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,n){var o=this.current,r=!1,h=o.lastCalcEvent,d=o.lastCalcData;h&&t.timeStamp-h.timeStamp>a.CALCULATE_INTERVAL&&(e=h.center,i=t.timeStamp-h.timeStamp,s=t.center.clientX-h.center.clientX,n=t.center.clientY-h.center.clientY,r=!0),(t.eventType==_||t.eventType==b)&&(o.futureCalcEvent=t),(!o.lastCalcEvent||r)&&(d.velocity=x.getVelocity(i,s,n),d.angle=x.getAngle(e,t.center),d.direction=x.getDirection(e,t.center),o.lastCalcEvent=o.futureCalcEvent||t,o.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 n=t.timeStamp-i.timeStamp,o=t.center.clientX-i.center.clientX,r=t.center.clientY-i.center.clientY;return this.getCalculatedData(t,s.center,n,o,r),x.extend(t,{startEvent:i,deltaTime:n,deltaX:o,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]===o&&(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,m,function(t){i.enabled&&t.eventType==m?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[m],this.eventStartHandler),null}},function(t){function e(e,s){var n=M.current;if(!(s.options.dragMaxTouches>0&&e.touches.length>s.options.dragMaxTouches))switch(e.eventType){case m:i=!1;break;case v:if(e.distance0)){var r=Math.abs(s.options.dragMinDistance/e.distance);o.pageX+=e.deltaX*r,o.pageY+=e.deltaY*r,o.clientX+=e.deltaX*r,o.clientY+=e.deltaY*r,e=M.extendEventData(e)}(n.lastEvent.dragLockToAxis||s.options.dragLockToAxis&&s.options.dragLockMinDistance<=e.distance)&&(e.dragLockToAxis=!0);var a=n.lastEvent.direction;e.dragLockToAxis&&a!==e.direction&&(e.direction=x.isVertical(a)?e.deltaY<0?c:d:e.deltaX<0?l:u),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 n=s.options,o=M.current;switch(e.eventType){case m:clearTimeout(i),o.name=t,i=setTimeout(function(){o&&o.name==t&&s.trigger(t,e)},n.holdTimeout);break;case v:e.distance>n.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 n,o,r=s.options,a=M.current,h=M.previous;switch(e.eventType){case m: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),n>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!==o&&(t.exports=s))}(window)},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,n=0;i>t&&s>n;)n%3==0?(this.forceAggregateHubs(!0),this.normalizeClusterLevels()):this.increaseClusterLevel(),i=this.nodeIndices.length,n+=1;n>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 n=this.moving,o=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=o.from,a=o.to;o.to.mass>o.from.mass&&(r=o.to,a=o.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.mass>e.mass?this._addToCluster(s,e,!0):this._addToCluster(e,s,!0))}}},e._clusterToSmallestNeighbour=function(t){for(var e=-1,i=null,s=0;sn.clusterSessions.length&&(e=n.clusterSessions.length,i=n)}null!=n&&void 0!==this.nodes[n.id]&&this._addToCluster(n,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 n,o,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 u=this.edges[d[c]];if(void 0!==u&&u.connected&&u.toId!=u.fromId&&(n=u.to.x-u.from.x,o=u.to.y-u.from.y,r=Math.sqrt(n*n+o*o),a>r)){h=!0;break}}if(!e&&h||e)for(c=0;l>c;c++)if(u=this.edges[d[c]],void 0!==u){var p=this.nodes[u.fromId==t.id?u.toId:u.fromId];p.dynamicEdges.length<=this.hubThreshold+s&&p.id!=t.id&&this._addToCluster(t,p,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 n=this.nodeIndices.length,o=e-this.constants.clustering.clusterLevelDifference;for(t in this.nodes)this.nodes.hasOwnProperty(t)&&this.nodes[t].clusterSessions.lengths&&(s=o.dynamicEdgesLength),t+=o.dynamicEdgesLength,e+=Math.pow(o.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,n=-1e9,o=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,n=-1e9,o=1e9,r=-1e9;for(var h in this.nodes)this.nodes.hasOwnProperty(h)&&(i=this.nodes[h],i.resize(t),o>i.x-.5*i.width&&(o=i.x-.5*i.width),ri.y-.5*i.height&&(s=i.y-.5*i.height),n0?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 n=this.nodes[s];if(!n)throw new RangeError('Node with id "'+s+'" not found');this._selectObject(n,!0,!0)}console.log("setSelection is deprecated. Please use selectNodes instead."),this.redraw()},e.selectNodes=function(t,e){var i,s,n;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++){n=t[i];var o=this.nodes[n];if(!o)throw new RangeError('Node with id "'+n+'" not found');this._selectObject(o,!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 n=this.edges[s];if(!n)throw new RangeError('Edge with id "'+s+'" not found');this._selectObject(n,!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),n=i(36),o=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 n=document.getElementById("network-manipulation-closeDiv");n.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 o=document.getElementById("network-manipulate-editModeButton");o.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 n({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 n({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 o({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.group,shape:t.shape,color:{background:t.color.background,border:t.color.border,highlight:{background:t.color.highlight.background,border:t.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);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=0;i0){"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,n=!1;for(e in this.nodes)this.nodes.hasOwnProperty(e)&&(t=this.nodes[e],-1!=t.level?s=!0:n=!0,is&&(o.xFixed=!1,o.x=i[o.level].minPos,r=!0):o.yFixed&&o.level>s&&(o.yFixed=!1,o.y=i[o.level].minPos,r=!0),1==r&&(i[o.level].minPos+=i[o.level].nodeSpacing,o.edges.length>1&&this._placeBranchNodes(o.edges,o.id,i,o.level))}},e._setLevel=function(t,e,i){for(var s=0;st)&&(n.level=t,e.length>1&&this._setLevel(t+1,n.edges,n.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 n(){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 o(){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 n=0;nthis.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,n,o=this.calculationNodes,r=this.constants.physics.centralGravity,a=0;for(n=0;nSimulation 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"),u=document.getElementById("graph_repositionNodes"),p=document.getElementById("graph_generateOptions");c.onclick=s.bind(this),u.onclick=n.bind(this),p.onclick=o.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(n(t))}function n(t){return o[t]||function(){throw new Error("Cannot find module '"+t+"'.")}()}var o={};s.keys=function(){return Object.keys(o)},s.resolve=n,t.exports=s},function(t,e){e._calculateNodeForces=function(){var t,e,i,s,n,o,r,a,h,d,l,c=this.calculationNodes,u=this.calculationNodeIndices,p=-2/3,f=4/3,g=this.constants.physics.repulsion.nodeDistance,m=g;for(d=0;di&&(r=.5*m>i?1:v*i+f,r*=0==o?1:1+o*this.constants.clustering.forceAmplification,r/=i,s=t*r,n=e*r,a.fx-=s,a.fy-=n,h.fx+=s,h.fy+=n)}}},function(t,e){e._calculateNodeForces=function(){var t,e,i,s,n,o,r,a,h,d,l=this.calculationNodes,c=this.calculationNodeIndices,u=this.constants.physics.hierarchicalRepulsion.nodeDistance;for(h=0;hi?-Math.pow(p*i,2)+Math.pow(p*u,2):0,0==i?i=.01:o/=i,s=t*o,n=e*o,r.fx-=s,r.fy-=n,a.fx+=s,a.fy+=n}},e._calculateHierarchicalSpringForces=function(){for(var t,e,i,s,n,o,r,a,h,d=this.edges,l=this.calculationNodes,c=this.calculationNodeIndices,u=0;uo;o++)t=e[i[o]],this._getForceContribution(n.root.children.NW,t),this._getForceContribution(n.root.children.NE,t),this._getForceContribution(n.root.children.SW,t),this._getForceContribution(n.root.children.SE,t)}},e._getForceContribution=function(t,e){if(t.childrenCount>0){var i,s,n;if(i=t.centerOfMass.x-e.x,s=t.centerOfMass.y-e.y,n=Math.sqrt(i*i+s*s),n*t.calcSize>this.constants.physics.barnesHut.theta){0==n&&(n=.1*Math.random(),i=n);var o=this.constants.physics.barnesHut.gravitationalConstant*t.mass*e.mass/(n*n*n),r=i*o,a=s*o;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==n&&(n=.5*Math.random(),i=n);var o=this.constants.physics.barnesHut.gravitationalConstant*t.mass*e.mass/(n*n*n),r=i*o,a=s*o;e.fx+=r,e.fy+=a}}},e._formBarnesHutTree=function(t,e){for(var i,s=e.length,n=Number.MAX_VALUE,o=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;n>d&&(n=d),d>r&&(r=d),o>l&&(o=l),l>a&&(a=l)}var c=Math.abs(r-n)-Math.abs(a-o);c>0?(o-=.5*c,a+=.5*c):(n+=.5*c,r-=.5*c);var u=1e-5,p=Math.max(u,Math.abs(r-n)),f=.5*p,g=.5*(n+r),m=.5*(o+a),v={root:{centerOfMass:{x:0,y:0},mass:0,range:{minX:g-f,maxX:g+f,minY:m-f,maxY:m+f},size:p,calcSize:1/p,children:{data:null},maxWidth:0,level:0,childrenCount:4}};for(this._splitBranch(v.root),h=0;s>h;h++)i=t[e[h]],this._placeInTree(v.root,i);this.barnesHutTree=v},e._updateBranchMass=function(t,e){var i=t.mass+e.mass,s=1/i;t.centerOfMass.x=t.centerOfMass.x*t.mass+e.x*e.mass,t.centerOfMass.x*=s,t.centerOfMass.y=t.centerOfMass.y*t.mass+e.y*e.mass,t.centerOfMass.y*=s,t.mass=i;var n=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,n,o,r=.5*t.size;switch(e){case"NW":i=t.range.minX,s=t.range.minX+r,n=t.range.minY,o=t.range.minY+r;break;case"NE":i=t.range.minX+r,s=t.range.maxX,n=t.range.minY,o=t.range.minY+r;break;case"SW":i=t.range.minX,s=t.range.minX+r,n=t.range.minY+r,o=t.range.maxY;break;case"SE":i=t.range.minX+r,s=t.range.maxX,n=t.range.minY+r,o=t.range.maxY}t.children[e]={centerOfMass:{x:0,y:0},mass:0,range:{minX:i,maxX:s,minY:n,maxY:o},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/lib/timeline/component/Group.js b/lib/timeline/component/Group.js index e23d8f06..3ca823e3 100644 --- a/lib/timeline/component/Group.js +++ b/lib/timeline/component/Group.js @@ -258,7 +258,7 @@ Group.prototype.add = function(item) { this.items[item.id] = item; item.setParent(this); - if (item instanceof ItemRange && this.visibleItems.indexOf(item) == -1) { + 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); }