diff --git a/dist/vis.js b/dist/vis.js index 146d535f..bd41724b 100644 --- a/dist/vis.js +++ b/dist/vis.js @@ -5,7 +5,7 @@ * A dynamic, browser-based visualization library. * * @version 3.10.1-SNAPSHOT - * @date 2015-02-18 + * @date 2015-02-20 * * @license * Copyright (C) 2011-2014 Almende B.V, http://almende.com @@ -83,67 +83,67 @@ return /******/ (function(modules) { // webpackBootstrap // utils exports.util = __webpack_require__(1); - exports.DOMutil = __webpack_require__(2); + exports.DOMutil = __webpack_require__(6); // data - exports.DataSet = __webpack_require__(3); - exports.DataView = __webpack_require__(4); - exports.Queue = __webpack_require__(5); + exports.DataSet = __webpack_require__(7); + exports.DataView = __webpack_require__(9); + exports.Queue = __webpack_require__(8); // Graph3d - exports.Graph3d = __webpack_require__(6); + exports.Graph3d = __webpack_require__(10); exports.graph3d = { - Camera: __webpack_require__(7), - Filter: __webpack_require__(8), - Point2d: __webpack_require__(9), - Point3d: __webpack_require__(10), - Slider: __webpack_require__(11), - StepNumber: __webpack_require__(12) + Camera: __webpack_require__(14), + Filter: __webpack_require__(15), + Point2d: __webpack_require__(13), + Point3d: __webpack_require__(12), + Slider: __webpack_require__(16), + StepNumber: __webpack_require__(17) }; // Timeline - exports.Timeline = __webpack_require__(13); - exports.Graph2d = __webpack_require__(14); + exports.Timeline = __webpack_require__(18); + exports.Graph2d = __webpack_require__(42); exports.timeline = { - DateUtil: __webpack_require__(15), - DataStep: __webpack_require__(16), - Range: __webpack_require__(17), - stack: __webpack_require__(18), - TimeStep: __webpack_require__(19), + DateUtil: __webpack_require__(24), + DataStep: __webpack_require__(45), + Range: __webpack_require__(21), + stack: __webpack_require__(29), + TimeStep: __webpack_require__(27), components: { items: { Item: __webpack_require__(31), - BackgroundItem: __webpack_require__(32), + BackgroundItem: __webpack_require__(35), BoxItem: __webpack_require__(33), PointItem: __webpack_require__(34), - RangeItem: __webpack_require__(35) + RangeItem: __webpack_require__(30) }, - Component: __webpack_require__(20), - CurrentTime: __webpack_require__(21), - CustomTime: __webpack_require__(22), - DataAxis: __webpack_require__(23), - GraphGroup: __webpack_require__(24), - Group: __webpack_require__(25), - BackgroundGroup: __webpack_require__(26), - ItemSet: __webpack_require__(27), - Legend: __webpack_require__(28), - LineGraph: __webpack_require__(29), - TimeAxis: __webpack_require__(30) + Component: __webpack_require__(23), + CurrentTime: __webpack_require__(39), + CustomTime: __webpack_require__(41), + DataAxis: __webpack_require__(44), + GraphGroup: __webpack_require__(46), + Group: __webpack_require__(28), + BackgroundGroup: __webpack_require__(32), + ItemSet: __webpack_require__(26), + Legend: __webpack_require__(50), + LineGraph: __webpack_require__(43), + TimeAxis: __webpack_require__(38) } }; // Network - exports.Network = __webpack_require__(36); + exports.Network = __webpack_require__(51); exports.network = { - Edge: __webpack_require__(37), - Groups: __webpack_require__(38), - Images: __webpack_require__(39), - Node: __webpack_require__(40), - Popup: __webpack_require__(41), - dotparser: __webpack_require__(42), - gephiParser: __webpack_require__(43) + Edge: __webpack_require__(57), + Groups: __webpack_require__(54), + Images: __webpack_require__(55), + Node: __webpack_require__(56), + Popup: __webpack_require__(58), + dotparser: __webpack_require__(52), + gephiParser: __webpack_require__(53) }; // Deprecated since v3.0.0 @@ -152,8 +152,8 @@ return /******/ (function(modules) { // webpackBootstrap }; // bundled external libraries - exports.moment = __webpack_require__(44); - exports.hammer = __webpack_require__(45); + exports.moment = __webpack_require__(2); + exports.hammer = __webpack_require__(19); /***/ }, @@ -164,7 +164,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__(44); + var moment = __webpack_require__(2); /** * Test whether given object is a number @@ -387,22 +387,24 @@ return /******/ (function(modules) { // webpackBootstrap * Deep extend an object a with the properties of object b * @param {Object} a * @param {Object} b + * @param {Boolean} protoExtend --> optional parameter. If true, the prototype values will also be extended. + * (ie. the options objects that inherit from others will also get the inherited options) * @returns {Object} */ - exports.deepExtend = function(a, b) { + exports.deepExtend = function(a, b, protoExtend) { // TODO: add support for Arrays to deepExtend if (Array.isArray(b)) { throw new TypeError('Arrays are not supported by deepExtend'); } for (var prop in b) { - if (b.hasOwnProperty(prop)) { + if (b.hasOwnProperty(prop) || protoExtend === true) { if (b[prop] && b[prop].constructor === Object) { if (a[prop] === undefined) { a[prop] = {}; } if (a[prop].constructor === Object) { - exports.deepExtend(a[prop], b[prop]); + exports.deepExtend(a[prop], b[prop], protoExtend); } else { a[prop] = b[prop]; @@ -1438,22260 +1440,20952 @@ return /******/ (function(modules) { // webpackBootstrap /* 2 */ /***/ function(module, exports, __webpack_require__) { - // 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 = []; - } - } - }; - - /** - * 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 = []; - } - } - } - }; - - /** - * 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; - }; - - - /** - * 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, insertBefore) { - var element; - // allocate DOM element, if it doesnt yet exist, create one. - if (JSONcontainer.hasOwnProperty(elementType)) { // this element has been created before - // check if there is an redundant element - if (JSONcontainer[elementType].redundant.length > 0) { - element = JSONcontainer[elementType].redundant[0]; - JSONcontainer[elementType].redundant.shift(); - } - else { - // create a new element and add it to the SVG - element = document.createElement(elementType); - if (insertBefore !== undefined) { - DOMContainer.insertBefore(element, insertBefore); - } - else { - 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: []}; - if (insertBefore !== undefined) { - DOMContainer.insertBefore(element, insertBefore); - } - else { - DOMContainer.appendChild(element); - } - } - JSONcontainer[elementType].used.push(element); - return element; - }; - - - - - /** - * 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 - * @param labelObj - * @returns {*} - */ - exports.drawPoint = function(x, y, group, JSONcontainer, svgContainer, labelObj) { - 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); - } - 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); - } + // 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); - if(group.options.drawPoints.styles !== undefined) { - point.setAttributeNS(null, "style", group.group.options.drawPoints.styles); - } - point.setAttributeNS(null, "class", group.className + " point"); - //handle label - var label = exports.getSVGElement('text',JSONcontainer,svgContainer); - if (labelObj){ - if (labelObj.xOffset) { - x = x + labelObj.xOffset; - } - if (labelObj.yOffset) { - y = y + labelObj.yOffset; - } - if (labelObj.content) { - label.textContent = labelObj.content; - } +/***/ }, +/* 3 */ +/***/ function(module, exports, __webpack_require__) { - if (labelObj.className) { - label.setAttributeNS(null, "class", labelObj.className + " label"); - } + var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(global, module) {//! moment.js + //! version : 2.9.0 + //! authors : Tim Wood, Iskren Chernev, Moment.js contributors + //! license : MIT + //! momentjs.com + (function (undefined) { + /************************************ + Constants + ************************************/ - } - label.setAttributeNS(null, "x", x); - label.setAttributeNS(null, "y", y); - return point; - }; + var moment, + VERSION = '2.9.0', + // the global-scope this is NOT the global object in Node.js + globalScope = (typeof global !== 'undefined' && (typeof window === 'undefined' || window === global.window)) ? global : this, + oldGlobalMoment, + round = Math.round, + hasOwnProperty = Object.prototype.hasOwnProperty, + i, - /** - * draw a bar SVG element centered on the X coordinate - * - * @param x - * @param y - * @param className - */ - exports.drawBar = function (x, y, width, height, className, JSONcontainer, svgContainer) { - if (height != 0) { - if (height < 0) { - height *= -1; - y -= height; - } - var rect = exports.getSVGElement('rect',JSONcontainer, svgContainer); - rect.setAttributeNS(null, "x", x - 0.5 * width); - rect.setAttributeNS(null, "y", y); - rect.setAttributeNS(null, "width", width); - rect.setAttributeNS(null, "height", height); - rect.setAttributeNS(null, "class", className); - } - }; + YEAR = 0, + MONTH = 1, + DATE = 2, + HOUR = 3, + MINUTE = 4, + SECOND = 5, + MILLISECOND = 6, -/***/ }, -/* 3 */ -/***/ function(module, exports, __webpack_require__) { + // internal storage for locale config files + locales = {}, - var util = __webpack_require__(1); - var Queue = __webpack_require__(5); + // extra moment internal properties (plugins register props here) + momentProperties = [], - /** - * 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, - // TODO: make this function deprecated (replaced with `on` since version 0.5) - DataSet.prototype.subscribe = DataSet.prototype.on; + // 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 + }, - /** - * 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); - }); - } - }; + 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' + }, - // TODO: make this function deprecated (replaced with `on` since version 0.5) - DataSet.prototype.unsubscribe = DataSet.prototype.off; + camelFunctions = { + dayofyear : 'dayOfYear', + isoweekday : 'isoWeekday', + isoweek : 'isoWeek', + weekyear : 'weekYear', + isoweekyear : 'isoWeekYear' + }, - /** - * 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 *'); - } + // format function strings + formatFunctions = {}, - var subscribers = []; - if (event in this._subscribers) { - subscribers = subscribers.concat(this._subscribers[event]); - } - if ('*' in this._subscribers) { - subscribers = subscribers.concat(this._subscribers['*']); - } + // default relative time thresholds + relativeTimeThresholds = { + s: 45, // seconds to minute + m: 45, // minutes to hour + h: 22, // hours to day + d: 26, // days to month + M: 11 // months to year + }, - for (var i = 0; i < subscribers.length; i++) { - var subscriber = subscribers[i]; - if (subscriber.callback) { - subscriber.callback(event, params, senderId || null); - } - } - }; + // tokens to ordinalize and pad + ordinalizeTokens = 'DDD w W M D d'.split(' '), + paddedTokens = 'M D H h m s w W'.split(' '), - /** - * 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; - - 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); - } + formatTokenFunctions = { + M : function () { + return this.month() + 1; + }, + MMM : function (format) { + return this.localeData().monthsShort(this, format); + }, + MMMM : function (format) { + return this.localeData().months(this, format); + }, + D : function () { + return this.date(); + }, + DDD : function () { + return this.dayOfYear(); + }, + d : function () { + return this.day(); + }, + dd : function (format) { + return this.localeData().weekdaysMin(this, format); + }, + ddd : function (format) { + return this.localeData().weekdaysShort(this, format); + }, + dddd : function (format) { + return this.localeData().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.localeData().meridiem(this.hours(), this.minutes(), true); + }, + A : function () { + return this.localeData().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.utcOffset(), + b = '+'; + if (a < 0) { + a = -a; + b = '-'; + } + return b + leftZeroFill(toInt(a / 60), 2) + ':' + leftZeroFill(toInt(a) % 60, 2); + }, + ZZ : function () { + var a = this.utcOffset(), + 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.valueOf(); + }, + X : function () { + return this.unix(); + }, + Q : function () { + return this.quarter(); + } + }, - id = me._addItem(item); - addedIds.push(id); - } - } - else if (data instanceof Object) { - // Single item - id = me._addItem(data); - addedIds.push(id); - } - else { - throw new Error('Unknown dataType'); - } + deprecations = {}, - if (addedIds.length) { - this._trigger('add', {items: addedIds}, senderId); - } + lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin'], - return addedIds; - }; + updateInProgress = false; - /** - * 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 = []; - var updatedIds = []; - var updatedData = []; - var me = this; - var fieldId = me._fieldId; + // 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'); + } + } - var addOrUpdate = function (item) { - var id = item[fieldId]; - if (me._data[id]) { - // update item - id = me._updateItem(item); - updatedIds.push(id); - updatedData.push(item); + function hasOwnProp(a, b) { + return hasOwnProperty.call(a, b); } - else { - // add new item - id = me._addItem(item); - addedIds.push(id); + + 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 + }; } - }; - if (Array.isArray(data)) { - // Array - for (var i = 0, len = data.length; i < len; i++) { - addOrUpdate(data[i]); + function printMsg(msg) { + if (moment.suppressDeprecationWarnings === false && + typeof console !== 'undefined' && console.warn) { + console.warn('Deprecation warning: ' + msg); + } } - } - 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); + function deprecate(msg, fn) { + var firstTime = true; + return extend(function () { + if (firstTime) { + printMsg(msg); + firstTime = false; + } + return fn.apply(this, arguments); + }, fn); } - } - 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, data: updatedData}, senderId); - } + function deprecateSimple(name, msg) { + if (!deprecations[name]) { + printMsg(msg); + deprecations[name] = true; + } + } - return addedIds.concat(updatedIds); - }; + function padToken(func, count) { + return function (a) { + return leftZeroFill(func.call(this, a), count); + }; + } + function ordinalizeToken(func, period) { + return function (a) { + return this.localeData().ordinal(func.call(this, a), period); + }; + } - /** - * 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; + function monthDiff(a, b) { + // difference in months + var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()), + // b is in (anchor - 1 month, anchor + 1 month) + anchor = a.clone().add(wholeMonthDiff, 'months'), + anchor2, adjust; - // parse the arguments - var id, ids, options, data; - var firstType = util.getType(arguments[0]); - if (firstType == 'String' || firstType == 'Number') { - // get(id [, options] [, data]) - id = arguments[0]; - options = arguments[1]; - data = arguments[2]; - } - else if (firstType == 'Array') { - // get(ids [, options] [, data]) - ids = arguments[0]; - options = arguments[1]; - data = arguments[2]; - } - else { - // get([, options] [, data]) - options = arguments[0]; - data = arguments[1]; - } + if (b - anchor < 0) { + anchor2 = a.clone().add(wholeMonthDiff - 1, 'months'); + // linear across the month + adjust = (b - anchor) / (anchor - anchor2); + } else { + anchor2 = a.clone().add(wholeMonthDiff + 1, 'months'); + // linear across the month + adjust = (b - anchor) / (anchor2 - anchor); + } - // 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 -(wholeMonthDiff + adjust); + } - 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 + ')'); + while (ordinalizeTokens.length) { + i = ordinalizeTokens.pop(); + formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i], i); } - if (returnType == 'DataTable' && !util.isDataTable(data)) { - throw new Error('Parameter "data" must be a DataTable ' + - 'when options.type is "DataTable"'); + while (paddedTokens.length) { + i = paddedTokens.pop(); + formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2); } - } - else if (data) { - returnType = (util.getType(data) == 'DataTable') ? 'DataTable' : 'Array'; - } - else { - returnType = 'Array'; - } + formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3); - // build options - var type = options && options.type || this._options.type; - var filter = options && options.filter; - var items = [], item, itemId, i, len; - // 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); + function meridiemFixWrap(locale, hour, meridiem) { + var isPm; + + if (meridiem == null) { + // nothing to do + return hour; + } + if (locale.meridiemHour != null) { + return locale.meridiemHour(hour, meridiem); + } else if (locale.isPM != null) { + // Fallback + isPm = locale.isPM(meridiem); + if (isPm && hour < 12) { + hour += 12; + } + if (!isPm && hour === 12) { + hour = 0; + } + return hour; + } else { + // thie is not supposed to happen + return hour; } - } } - } - // order the results - if (options && options.order && id == undefined) { - this._sort(items, options.order); - } + /************************************ + Constructors + ************************************/ - // 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); - } + function Locale() { } - } - // 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; - } - 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]); + // Moment prototype object + function Moment(config, skipOverflow) { + if (skipOverflow !== false) { + checkOverflow(config); + } + copyConfig(this, config); + this._d = new Date(+config._d); + // Prevent infinite loop in case updateOffset creates new moment + // objects. + if (updateInProgress === false) { + updateInProgress = true; + moment.updateOffset(this); + updateInProgress = false; } - return data; - } - else { - // just return our array - return items; - } } - } - }; - /** - * 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 = []; + // 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; - 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); - } - } - } + // 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._sort(items, order); + this._data = {}; - 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._locale = moment.localeData(); + + this._bubble(); } - } - else { - // get all items - if (order) { - // create an ordered list - items = []; - for (id in data) { - if (data.hasOwnProperty(id)) { - items.push(data[id]); + + /************************************ + Helpers + ************************************/ + + + function extend(a, b) { + for (var i in b) { + if (hasOwnProp(b, i)) { + a[i] = b[i]; + } } - } - this._sort(items, order); + if (hasOwnProp(b, 'toString')) { + a.toString = b.toString; + } - for (i = 0, len = items.length; i < len; i++) { - ids[i] = items[i][this._fieldId]; - } - } - else { - // create unordered list - for (id in data) { - if (data.hasOwnProperty(id)) { - item = data[id]; - ids.push(item[this._fieldId]); + if (hasOwnProp(b, 'valueOf')) { + a.valueOf = b.valueOf; } - } - } - } - return ids; - }; + return a; + } - /** - * 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; - }; + function copyConfig(to, from) { + var i, prop, val; - /** - * 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; + if (typeof from._isAMomentObject !== 'undefined') { + to._isAMomentObject = from._isAMomentObject; + } + if (typeof from._i !== 'undefined') { + to._i = from._i; + } + if (typeof from._f !== 'undefined') { + to._f = from._f; + } + if (typeof from._l !== 'undefined') { + to._l = from._l; + } + if (typeof from._strict !== 'undefined') { + to._strict = from._strict; + } + if (typeof from._tzm !== 'undefined') { + to._tzm = from._tzm; + } + if (typeof from._isUTC !== 'undefined') { + to._isUTC = from._isUTC; + } + if (typeof from._offset !== 'undefined') { + to._offset = from._offset; + } + if (typeof from._pf !== 'undefined') { + to._pf = from._pf; + } + if (typeof from._locale !== 'undefined') { + to._locale = from._locale; + } - if (options && options.order) { - // execute forEach on ordered list - var items = this.get(options); + if (momentProperties.length > 0) { + for (i in momentProperties) { + prop = momentProperties[i]; + val = from[prop]; + if (typeof val !== 'undefined') { + to[prop] = val; + } + } + } - for (var i = 0, len = items.length; i < len; i++) { - item = items[i]; - id = item[this._fieldId]; - callback(item, id); + return to; } - } - else { - // unordered - for (id in data) { - if (data.hasOwnProperty(id)) { - item = this._getItem(id, type); - if (!filter || filter(item)) { - callback(item, id); + + function absRound(number) { + if (number < 0) { + return Math.ceil(number); + } else { + return Math.floor(number); } - } } - } - }; - /** - * 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; + // 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; - // 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)); - } + while (output.length < targetLength) { + output = '0' + output; + } + return (sign ? (forceSign ? '+' : '') : '-') + output; } - } - // order items - if (options && options.order) { - this._sort(mappedItems, options.order); - } + function positiveMomentsDifference(base, other) { + var res = {milliseconds: 0, months: 0}; - return mappedItems; - }; + res.months = other.month() - base.month() + + (other.year() - base.year()) * 12; + if (base.clone().add(res.months, 'M').isAfter(other)) { + --res.months; + } - /** - * Filter the fields of an item - * @param {Object | null} item - * @param {String[]} fields Field names - * @return {Object | null} filteredItem or null if no item is provided - * @private - */ - DataSet.prototype._filterFields = function (item, fields) { - if (!item) { // item is null - return item; - } + res.milliseconds = +other - +(base.clone().add(res.months, 'M')); - var filteredItem = {}; + return res; + } - for (var field in item) { - if (item.hasOwnProperty(field) && (fields.indexOf(field) != -1)) { - filteredItem[field] = item[field]; + function momentsDifference(base, other) { + var res; + other = makeAs(other, base); + if (base.isBefore(other)) { + res = positiveMomentsDifference(base, other); + } else { + res = positiveMomentsDifference(other, base); + res.milliseconds = -res.milliseconds; + res.months = -res.months; + } + + return res; } - } - return filteredItem; - }; + // TODO: remove 'name' arg after deprecation is removed + function createAdder(direction, name) { + return function (val, period) { + var dur, tmp; + //invert the arguments, but complain about it + if (period !== null && !isNaN(+period)) { + deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period).'); + tmp = val; val = period; period = tmp; + } - /** - * 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'); - } - }; + val = typeof val === 'string' ? +val : val; + dur = moment.duration(val, period); + addOrSubtractDurationFromMoment(this, dur, direction); + return this; + }; + } - /** - * 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; + function addOrSubtractDurationFromMoment(mom, duration, isAdding, updateOffset) { + var milliseconds = duration._milliseconds, + days = duration._days, + months = duration._months; + updateOffset = updateOffset == null ? true : updateOffset; - 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 (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); + } } - } - else { - removedId = this._remove(id); - if (removedId != null) { - removedIds.push(removedId); + + // check if is an array + function isArray(input) { + return Object.prototype.toString.call(input) === '[object Array]'; } - } - if (removedIds.length) { - this._trigger('remove', {items: removedIds}, senderId); - } + function isDate(input) { + return Object.prototype.toString.call(input) === '[object Date]' || + input instanceof Date; + } - return removedIds; - }; + // compare two arrays, return the number of differences + function compareArrays(array1, array2, dontConvert) { + var len = Math.min(array1.length, array2.length), + lengthDiff = Math.abs(array1.length - array2.length), + diffs = 0, + i; + for (i = 0; i < len; i++) { + if ((dontConvert && array1[i] !== array2[i]) || + (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) { + diffs++; + } + } + return diffs + lengthDiff; + } - /** - * Remove 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]; - this.length--; - return id; + function normalizeUnits(units) { + if (units) { + var lowered = units.toLowerCase().replace(/(.)s$/, '$1'); + units = unitAliases[units] || camelFunctions[lowered] || lowered; + } + return units; } - } - else if (id instanceof Object) { - var itemId = id[this._fieldId]; - if (itemId && this._data[itemId]) { - delete this._data[itemId]; - this.length--; - return itemId; + + function normalizeObjectUnits(inputObject) { + var normalizedInput = {}, + normalizedProp, + prop; + + for (prop in inputObject) { + if (hasOwnProp(inputObject, prop)) { + normalizedProp = normalizeUnits(prop); + if (normalizedProp) { + normalizedInput[normalizedProp] = inputObject[prop]; + } + } + } + + return normalizedInput; } - } - return null; - }; - /** - * Clear the data - * @param {String} [senderId] Optional sender id - * @return {Array} removedIds The ids of all removed items - */ - DataSet.prototype.clear = function (senderId) { - var ids = Object.keys(this._data); + function makeList(field) { + var count, setter; - this._data = {}; - this.length = 0; + if (field.indexOf('week') === 0) { + count = 7; + setter = 'day'; + } + else if (field.indexOf('month') === 0) { + count = 12; + setter = 'month'; + } + else { + return; + } - this._trigger('remove', {items: ids}, senderId); + moment[field] = function (format, index) { + var i, getter, + method = moment._locale[field], + results = []; - return ids; - }; + if (typeof format === 'number') { + index = format; + format = undefined; + } - /** - * 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; + getter = function (i) { + var m = moment().utc().set(setter, i); + return method.call(moment._locale, m, format || ''); + }; - 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; - } + if (index != null) { + return getter(index); + } + else { + for (i = 0; i < count; i++) { + results.push(getter(i)); + } + return results; + } + }; } - } - return max; - }; + function toInt(argumentForCoercion) { + var coercedNumber = +argumentForCoercion, + value = 0; - /** - * 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; + if (coercedNumber !== 0 && isFinite(coercedNumber)) { + if (coercedNumber >= 0) { + value = Math.floor(coercedNumber); + } else { + value = Math.ceil(coercedNumber); + } + } - 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; - } + return value; } - } - return min; - }; + function daysInMonth(year, month) { + return new Date(Date.UTC(year, month + 1, 0)).getUTCDate(); + } - /** - * 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; + function weeksInYear(year, dow, doy) { + return weekOfYear(moment([year, 11, 31 + dow - doy]), dow, doy).week; + } - 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++; - } + function daysInYear(year) { + return isLeapYear(year) ? 366 : 365; } - } - if (fieldType) { - for (i = 0; i < values.length; i++) { - values[i] = util.convert(values[i], fieldType); + function isLeapYear(year) { + return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; } - } - return values; - }; + 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] > 24 || + (m._a[HOUR] === 24 && (m._a[MINUTE] !== 0 || + m._a[SECOND] !== 0 || + m._a[MILLISECOND] !== 0)) ? 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; - /** - * Add a single item. Will fail when an item with the same id already exists. - * @param {Object} item - * @return {String} id - * @private - */ - DataSet.prototype._addItem = function (item) { - var id = item[this._fieldId]; + if (m._pf._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) { + overflow = DATE; + } - 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'); + m._pf.overflow = overflow; + } } - } - else { - // generate an id - id = util.randomUUID(); - item[this._fieldId] = id; - } - 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); + 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 (m._strict) { + m._isValid = m._isValid && + m._pf.charsLeftOver === 0 && + m._pf.unusedTokens.length === 0 && + m._pf.bigHour === undefined; + } + } + return m._isValid; } - } - this._data[id] = d; - this.length++; - return id; - }; + function normalizeLocale(key) { + return key ? key.toLowerCase().replace('_', '-') : key; + } - /** - * 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; + // pick the locale 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 + function chooseLocale(names) { + var i = 0, j, next, locale, split; - // get the item from the dataset - var raw = this._data[id]; - if (!raw) { - return null; - } + while (i < names.length) { + split = normalizeLocale(names[i]).split('-'); + j = split.length; + next = normalizeLocale(names[i + 1]); + next = next ? next.split('-') : null; + while (j > 0) { + locale = loadLocale(split.slice(0, j).join('-')); + if (locale) { + return locale; + } + 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 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]); - } + function loadLocale(name) { + var oldLocale = null; + if (!locales[name] && hasModule) { + try { + oldLocale = moment.locale(); + !(function webpackMissingModule() { var e = new Error("Cannot find module \"./locale\""); e.code = 'MODULE_NOT_FOUND'; throw e; }()); + // because defineLocale currently also sets the global locale, we want to undo that for lazy loaded locales + moment.locale(oldLocale); + } catch (e) { } + } + return locales[name]; } - } - else { - // no field types specified, no converting needed - for (field in raw) { - if (raw.hasOwnProperty(field)) { - value = raw[field]; - converted[field] = value; - } + + // Return a moment from input, that is local/utc/utcOffset equivalent to + // model. + function makeAs(input, model) { + var res, diff; + if (model._isUTC) { + res = model.clone(); + diff = (moment.isMoment(input) || isDate(input) ? + +input : +moment(input)) - (+res); + // Use low-level api, because this fn is low-level api. + res._d.setTime(+res._d + diff); + moment.updateOffset(res, false); + return res; + } else { + return moment(input).local(); + } } - } - return converted; - }; - /** - * 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'); - } + /************************************ + Locale + ************************************/ - // 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); - } - } - return id; - }; + extend(Locale.prototype, { - /** - * 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; - }; + set : function (config) { + var prop, i; + for (i in config) { + prop = config[i]; + if (typeof prop === 'function') { + this[i] = prop; + } else { + this['_' + i] = prop; + } + } + // Lenient ordinal parsing accepts just a number in addition to + // number + (possibly) stuff coming from _ordinalParseLenient. + this._ordinalParseLenient = new RegExp(this._ordinalParse.source + '|' + /\d{1,2}/.source); + }, - /** - * 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(); + _months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), + months : function (m) { + return this._months[m.month()]; + }, - for (var col = 0, cols = columns.length; col < cols; col++) { - var field = columns[col]; - dataTable.setValue(row, col, item[field]); - } - }; + _monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), + monthsShort : function (m) { + return this._monthsShort[m.month()]; + }, - module.exports = DataSet; + monthsParse : function (monthName, format, strict) { + var i, mom, regex; + if (!this._monthsParse) { + this._monthsParse = []; + this._longMonthsParse = []; + this._shortMonthsParse = []; + } -/***/ }, -/* 4 */ -/***/ function(module, exports, __webpack_require__) { + for (i = 0; i < 12; i++) { + // make the regex if we don't have it already + mom = moment.utc([2000, i]); + if (strict && !this._longMonthsParse[i]) { + this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i'); + this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i'); + } + if (!strict && !this._monthsParse[i]) { + regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, ''); + this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i'); + } + // test the regex + if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) { + return i; + } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) { + return i; + } else if (!strict && this._monthsParse[i].test(monthName)) { + return i; + } + } + }, - var util = __webpack_require__(1); - var DataSet = __webpack_require__(3); + _weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), + weekdays : function (m) { + return this._weekdays[m.day()]; + }, - /** - * 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.length = 0; // number of items in the DataView - this._options = options || {}; - this._fieldId = 'id'; // name of the field containing id - this._subscribers = {}; // event subscribers + _weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), + weekdaysShort : function (m) { + return this._weekdaysShort[m.day()]; + }, - var me = this; - this.listener = function () { - me._onEvent.apply(me, arguments); - }; + _weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), + weekdaysMin : function (m) { + return this._weekdaysMin[m.day()]; + }, - this.setData(data); - } + weekdaysParse : function (weekdayName) { + var i, mom, regex; - // TODO: implement a function .config() to dynamically update things like configured filter - // and trigger changes accordingly + if (!this._weekdaysParse) { + this._weekdaysParse = []; + } - /** - * Set a data source for the view - * @param {DataSet | DataView} data - */ - DataView.prototype.setData = function (data) { - var ids, i, len; + 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; + } + } + }, - if (this._data) { - // unsubscribe from current dataset - if (this._data.unsubscribe) { - this._data.unsubscribe('*', this.listener); - } + _longDateFormat : { + LTS : 'h:mm:ss A', + 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; + }, - // 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.length = 0; - this._trigger('remove', {items: ids}); - } + 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'); + }, - this._data = data; + _meridiemParse : /[ap]\.?m?\.?/i, + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'pm' : 'PM'; + } else { + return isLower ? 'am' : 'AM'; + } + }, - 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.length = ids.length; - this._trigger('add', {items: ids}); + _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, now) { + var output = this._calendar[key]; + return typeof output === 'function' ? output.apply(mom, [now]) : output; + }, - // subscribe to new dataset - if (this._data.on) { - this._data.on('*', this.listener); - } - } - }; + _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' + }, - /** - * Refresh the DataView. Useful when the DataView has a filter function - * containing a variable parameter. - */ - DataView.prototype.refresh = function () { - var id; - var ids = this._data.getIds({filter: this._options && this._options.filter}); - var newIds = {}; - var added = []; - var removed = []; + 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); + }, - // check for additions - for (var i = 0; i < ids.length; i++) { - id = ids[i]; - newIds[id] = true; - if (!this._ids[id]) { - added.push(id); - this._ids[id] = true; - this.length++; - } - } - - // check for removals - for (id in this._ids) { - if (this._ids.hasOwnProperty(id)) { - if (!newIds[id]) { - removed.push(id); - delete this._ids[id]; - this.length--; - } - } - } - - // trigger events - if (added.length) { - this._trigger('add', {items: added}); - } - if (removed.length) { - this._trigger('remove', {items: removed}); - } - }; - - /** - * 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; + pastFuture : function (diff, output) { + var format = this._relativeTime[diff > 0 ? 'future' : 'past']; + return typeof format === 'function' ? format(output) : format.replace(/%s/i, output); + }, - // 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]; - } + ordinal : function (number) { + return this._ordinal.replace('%d', number); + }, + _ordinal : '%d', + _ordinalParse : /\d{1,2}/, - // extend the options with the default options and provided options - var viewOptions = util.extend({}, this._options, options); + preparse : function (string) { + return string; + }, - // 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); - } - } + postformat : function (string) { + return string; + }, - // build up the call to the linked data set - var getArguments = []; - if (ids != undefined) { - getArguments.push(ids); - } - getArguments.push(viewOptions); - getArguments.push(data); + week : function (mom) { + return weekOfYear(mom, this._week.dow, this._week.doy).week; + }, - return this._data && this._data.get.apply(this._data, getArguments); - }; + _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. + }, - /** - * 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; + firstDayOfWeek : function () { + return this._week.dow; + }, - if (this._data) { - var defaultFilter = this._options.filter; - var filter; + firstDayOfYear : function () { + return this._week.doy; + }, - if (options && options.filter) { - if (defaultFilter) { - filter = function (item) { - return defaultFilter(item) && options.filter(item); + _invalidDate: 'Invalid date', + invalidDate: function () { + return this._invalidDate; } - } - else { - filter = options.filter; - } - } - else { - filter = defaultFilter; - } - - ids = this._data.getIds({ - filter: filter, - order: options && options.order }); - } - else { - ids = []; - } - return ids; - }; - - /** - * 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; - }; + /************************************ + Formatting + ************************************/ - /** - * 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 (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); - } + function removeFormattingTokens(input) { + if (input.match(/\[[\s\S]/)) { + return input.replace(/^\[|\]$/g, ''); } + return input.replace(/\\/g, ''); + } - 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); + function makeFormatFunction(format) { + var array = format.match(formattingTokens), i, length; - 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 :-( + for (i = 0, length = array.length; i < length; i++) { + if (formatTokenFunctions[array[i]]) { + array[i] = formatTokenFunctions[array[i]]; + } else { + array[i] = removeFormattingTokens(array[i]); } - } } - break; + 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; + }; + } - 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); - } + // format date using native date object + function formatMoment(m, format) { + if (!m.isValid()) { + return m.localeData().invalidDate(); } - break; - } + format = expandFormat(format, m.localeData()); - this.length += added.length - removed.length; + if (!formatFunctions[format]) { + formatFunctions[format] = makeFormatFunction(format); + } - 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); + return formatFunctions[format](m); } - } - }; - - // copy subscription functionality from DataSet - DataView.prototype.on = DataSet.prototype.on; - DataView.prototype.off = DataSet.prototype.off; - DataView.prototype._trigger = DataSet.prototype._trigger; - - // TODO: make these functions deprecated (replaced with `on` and `off` since version 0.5) - DataView.prototype.subscribe = DataView.prototype.on; - DataView.prototype.unsubscribe = DataView.prototype.off; - - module.exports = DataView; - -/***/ }, -/* 5 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * A queue - * @param {Object} options - * Available options: - * - delay: number When provided, the queue will be flushed - * automatically after an inactivity of this delay - * in milliseconds. - * Default value is null. - * - max: number When the queue exceeds the given maximum number - * of entries, the queue is flushed automatically. - * Default value of max is Infinity. - * @constructor - */ - function Queue(options) { - // options - this.delay = null; - this.max = Infinity; - // properties - this._queue = []; - this._timeout = null; - this._extended = null; + function expandFormat(format, locale) { + var i = 5; - this.setOptions(options); - } + function replaceLongDateFormatTokens(input) { + return locale.longDateFormat(input) || input; + } - /** - * Update the configuration of the queue - * @param {Object} options - * Available options: - * - delay: number When provided, the queue will be flushed - * automatically after an inactivity of this delay - * in milliseconds. - * Default value is null. - * - max: number When the queue exceeds the given maximum number - * of entries, the queue is flushed automatically. - * Default value of max is Infinity. - * @param options - */ - Queue.prototype.setOptions = function (options) { - if (options && typeof options.delay !== 'undefined') { - this.delay = options.delay; - } - if (options && typeof options.max !== 'undefined') { - this.max = options.max; - } + localFormattingTokens.lastIndex = 0; + while (i >= 0 && localFormattingTokens.test(format)) { + format = format.replace(localFormattingTokens, replaceLongDateFormatTokens); + localFormattingTokens.lastIndex = 0; + i -= 1; + } - this._flushIfNeeded(); - }; + return format; + } - /** - * Extend an object with queuing functionality. - * The object will be extended with a function flush, and the methods provided - * in options.replace will be replaced with queued ones. - * @param {Object} object - * @param {Object} options - * Available options: - * - replace: Array. - * A list with method names of the methods - * on the object to be replaced with queued ones. - * - delay: number When provided, the queue will be flushed - * automatically after an inactivity of this delay - * in milliseconds. - * Default value is null. - * - max: number When the queue exceeds the given maximum number - * of entries, the queue is flushed automatically. - * Default value of max is Infinity. - * @return {Queue} Returns the created queue - */ - Queue.extend = function (object, options) { - var queue = new Queue(options); - if (object.flush !== undefined) { - throw new Error('Target object already has a property flush'); - } - object.flush = function () { - queue.flush(); - }; + /************************************ + Parsing + ************************************/ - var methods = [{ - name: 'flush', - original: undefined - }]; - if (options && options.replace) { - for (var i = 0; i < options.replace.length; i++) { - var name = options.replace[i]; - methods.push({ - name: name, - original: object[name] - }); - queue.replace(object, name); + // 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 config._locale._meridiemParse; + case 'x': + return parseTokenOffsetMs; + 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 strict ? config._locale._ordinalParse : config._locale._ordinalParseLenient; + default : + a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), 'i')); + return a; + } } - } - queue._extended = { - object: object, - methods: methods - }; + function utcOffsetFromString(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]); - return queue; - }; + return parts[0] === '+' ? minutes : -minutes; + } - /** - * Destroy the queue. The queue will first flush all queued actions, and in - * case it has extended an object, will restore the original object. - */ - Queue.prototype.destroy = function () { - this.flush(); + // function to convert string input to date + function addTimeToArrayFromToken(token, input, config) { + var a, datePartArray = config._a; - if (this._extended) { - var object = this._extended.object; - var methods = this._extended.methods; - for (var i = 0; i < methods.length; i++) { - var method = methods[i]; - if (method.original) { - object[method.name] = method.original; - } - else { - delete object[method.name]; - } + 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 = config._locale.monthsParse(input, token, config._strict); + // 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.match(/\d{1,2}/)[0], 10)); + } + break; + // DAY OF YEAR + case 'DDD' : // fall through to DDDD + case 'DDDD' : + if (input != null) { + config._dayOfYear = toInt(input); + } + + 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._meridiem = input; + // config._isPm = config._locale.isPM(input); + break; + // HOUR + case 'h' : // fall through to hh + case 'hh' : + config._pf.bigHour = true; + /* falls through */ + 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 OFFSET (MILLISECONDS) + case 'x': + config._d = new Date(toInt(input)); + 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 = utcOffsetFromString(input); + break; + // WEEKDAY - human + case 'dd': + case 'ddd': + case 'dddd': + a = config._locale.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); + } } - this._extended = null; - } - }; - /** - * Replace a method on an object with a queued version - * @param {Object} object Object having the method - * @param {string} method The method name - */ - Queue.prototype.replace = function(object, method) { - var me = this; - var original = object[method]; - if (!original) { - throw new Error('Method ' + method + ' undefined'); - } + function dayOfYearFromWeekInfo(config) { + var w, weekYear, week, weekday, dow, doy, temp; - object[method] = function () { - // create an Array with the arguments - var args = []; - for (var i = 0; i < arguments.length; i++) { - args[i] = arguments[i]; - } + w = config._w; + if (w.GG != null || w.W != null || w.E != null) { + dow = 1; + doy = 4; - // add this call to the queue - me.queue({ - args: args, - fn: original, - context: this - }); - }; - }; + // 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 { + dow = config._locale._week.dow; + doy = config._locale._week.doy; - /** - * Queue a call - * @param {function | {fn: function, args: Array} | {fn: function, args: Array, context: Object}} entry - */ - Queue.prototype.queue = function(entry) { - if (typeof entry === 'function') { - this._queue.push({fn: entry}); - } - else { - this._queue.push(entry); - } + weekYear = dfl(w.gg, config._a[YEAR], weekOfYear(moment(), dow, doy).year); + week = dfl(w.w, 1); - this._flushIfNeeded(); - }; + 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); - /** - * Check whether the queue needs to be flushed - * @private - */ - Queue.prototype._flushIfNeeded = function () { - // flush when the maximum is exceeded. - if (this._queue.length > this.max) { - this.flush(); - } + config._a[YEAR] = temp.year; + config._dayOfYear = temp.dayOfYear; + } - // flush after a period of inactivity when a delay is configured - clearTimeout(this._timeout); - if (this.queue.length > 0 && typeof this.delay === 'number') { - var me = this; - this._timeout = setTimeout(function () { - me.flush(); - }, this.delay); - } - }; + // 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; - /** - * Flush all queued calls - */ - Queue.prototype.flush = function () { - while (this._queue.length > 0) { - var entry = this._queue.shift(); - entry.fn.apply(entry.context || entry.fn, entry.args || []); - } - }; + if (config._d) { + return; + } - module.exports = Queue; + 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); + } -/***/ }, -/* 6 */ -/***/ function(module, exports, __webpack_require__) { + //if the day of the year is set, figure out what it is + if (config._dayOfYear) { + yearToUse = dfl(config._a[YEAR], currentDate[YEAR]); - var Emitter = __webpack_require__(56); - var DataSet = __webpack_require__(3); - var DataView = __webpack_require__(4); - var util = __webpack_require__(1); - var Point3d = __webpack_require__(10); - var Point2d = __webpack_require__(9); - var Camera = __webpack_require__(7); - var Filter = __webpack_require__(8); - var Slider = __webpack_require__(11); - var StepNumber = __webpack_require__(12); + if (config._dayOfYear > daysInYear(yearToUse)) { + config._pf._overflowDayOfYear = true; + } - /** - * @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'); - } + date = makeUTCDate(yearToUse, 0, config._dayOfYear); + config._a[MONTH] = date.getUTCMonth(); + config._a[DATE] = date.getUTCDate(); + } - // 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%'; + // Default to current date. + // * if no year, month, day of month are given, default to today + // * if day of month is given, default month and year + // * if month is given, default only year + // * if year is given, don't default anything + for (i = 0; i < 3 && config._a[i] == null; ++i) { + config._a[i] = input[i] = currentDate[i]; + } - this.xLabel = 'x'; - this.yLabel = 'y'; - this.zLabel = 'z'; + // 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]; + } - var passValueFn = function(v) { return v; }; - this.xValueLabel = passValueFn; - this.yValueLabel = passValueFn; - this.zValueLabel = passValueFn; - - this.filterLabel = 'time'; - this.legendLabel = 'value'; + // Check for 24:00:00.000 + if (config._a[HOUR] === 24 && + config._a[MINUTE] === 0 && + config._a[SECOND] === 0 && + config._a[MILLISECOND] === 0) { + config._nextDay = true; + config._a[HOUR] = 0; + } - 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' + config._d = (config._useUTC ? makeUTCDate : makeDate).apply(null, input); + // Apply timezone offset from input. The actual utcOffset can be changed + // with parseZone. + if (config._tzm != null) { + config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm); + } - this.animationInterval = 1000; // milliseconds - this.animationPreload = false; + if (config._nextDay) { + config._a[HOUR] = 24; + } + } - this.camera = new Camera(); - this.eye = new Point3d(0, 0, -1); // TODO: set eye.z about 3/4 of the width of the window? + function dateFromObject(config) { + var normalizedInput; - this.dataTable = null; // The original data table - this.dataPoints = null; // The table with point objects + if (config._d) { + return; + } - // the column indexes - this.colX = undefined; - this.colY = undefined; - this.colZ = undefined; - this.colValue = undefined; - this.colFilter = undefined; + normalizedInput = normalizeObjectUnits(config._i); + config._a = [ + normalizedInput.year, + normalizedInput.month, + normalizedInput.day || normalizedInput.date, + normalizedInput.hour, + normalizedInput.minute, + normalizedInput.second, + normalizedInput.millisecond + ]; - 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 + dateFromConfig(config); + } - // constants - this.colorAxis = '#4D4D4D'; - this.colorGrid = '#D3D3D3'; - this.colorDot = '#7DC1FF'; - this.colorDotBorder = '#3267D2'; + 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()]; + } + } - // create a frame and canvas - this.create(); + // date from string and format string + function makeDateFromStringAndFormat(config) { + if (config._f === moment.ISO_8601) { + parseISO(config); + return; + } - // apply options (also when undefined) - this.setOptions(options); + config._a = []; + config._pf.empty = true; - // apply data - if (data) { - this.setData(data); - } - } + // This array is used to make a Date, either with `new Date` or `Date.UTC` + var string = '' + config._i, + i, parsedInput, tokens, token, skipped, + stringLength = string.length, + totalParsedInputLength = 0; - // Extend Graph3d with an Emitter mixin - Emitter(Graph3d.prototype); + tokens = expandFormat(config._f, config._locale).match(formattingTokens) || []; - /** - * 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)); + 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); + } + } - // 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; + // add remaining unparsed input length to the string + config._pf.charsLeftOver = stringLength - totalParsedInputLength; + if (string.length > 0) { + config._pf.unusedInput.push(string); + } + + // clear _12h flag if hour is <= 12 + if (config._pf.bigHour === true && config._a[HOUR] <= 12) { + config._pf.bigHour = undefined; + } + // handle meridiem + config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], + config._meridiem); + dateFromConfig(config); + checkOverflow(config); } - else { - //noinspection JSSuspiciousNameCombination - this.scale.x = this.scale.y; + + function unescapeFormat(s) { + return s.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) { + return p1 || p2 || p3 || p4; + }); } - } - // scale the vertical axis - this.scale.z *= this.verticalRatio; - // TODO: can this be automated? verticalRatio? + // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript + function regexpEscape(s) { + return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); + } - // determine scale for (optional) value - this.scale.value = 1 / (this.valueMax - this.valueMin); + // date from string and array of format strings + function makeDateFromStringAndArray(config) { + var tempConfig, + bestMoment, - // 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); - }; - - - /** - * 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); - }; - - /** - * 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, + scoreToBeat, + i, + currentScore; - cx = this.camera.getCameraLocation().x, - cy = this.camera.getCameraLocation().y, - cz = this.camera.getCameraLocation().z, + if (config._f.length === 0) { + config._pf.invalidFormat = true; + config._d = new Date(NaN); + return; + } - // 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), + for (i = 0; i < config._f.length; i++) { + currentScore = 0; + tempConfig = copyConfig({}, config); + if (config._useUTC != null) { + tempConfig._useUTC = config._useUTC; + } + tempConfig._pf = defaultParsingFlags(); + tempConfig._f = config._f[i]; + makeDateFromStringAndFormat(tempConfig); - // 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)); + if (!isValid(tempConfig)) { + continue; + } - return new Point3d(dx, dy, dz); - }; + // if there is any input that was not parsed add a penalty for that format + currentScore += tempConfig._pf.charsLeftOver; - /** - * 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; + //or tokens + currentScore += tempConfig._pf.unusedTokens.length * 10; - // 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()); - } + tempConfig._pf.score = currentScore; - // 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 (scoreToBeat == null || currentScore < scoreToBeat) { + scoreToBeat = currentScore; + bestMoment = tempConfig; + } + } - /** - * 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; + extend(config, bestMoment || tempConfig); + } - 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'; - } + // date from iso format + function parseISO(config) { + var i, l, + string = config._i, + match = isoRegex.exec(string); - this.frame.style.backgroundColor = fill; - this.frame.style.borderColor = stroke; - this.frame.style.borderWidth = strokeWidth + 'px'; - this.frame.style.borderStyle = 'solid'; - }; + 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); + } + } - /// 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 - }; + function map(arr, fn) { + var res = [], i; + for (i = 0; i < arr.length; ++i) { + res.push(fn(arr[i], i)); + } + return res; + } - /** - * 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; - } + function makeDateFromInput(config) { + var input = config._i, matched; + if (input === undefined) { + config._d = new Date(); + } else if (isDate(input)) { + config._d = new Date(+input); + } else if ((matched = aspNetJsonRegex.exec(input)) !== null) { + config._d = new Date(+matched[1]); + } else if (typeof input === 'string') { + makeDateFromString(config); + } else if (isArray(input)) { + config._a = map(input.slice(0), function (obj) { + return parseInt(obj, 10); + }); + dateFromConfig(config); + } else if (typeof(input) === 'object') { + dateFromObject(config); + } else if (typeof(input) === 'number') { + // from milliseconds + config._d = new Date(input); + } else { + moment.createFromInputFallback(config); + } + } - return -1; - }; + 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); - /** - * 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; + //the date constructor doesn't accept years < 1970 + if (y < 1970) { + date.setFullYear(y); + } + return date; + } - if (data.getNumberOfColumns() > 3) { - this.colFilter = 3; + function makeUTCDate(y) { + var date = new Date(Date.UTC.apply(null, arguments)); + if (y < 1970) { + date.setUTCFullYear(y); + } + return date; } - } - 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; - if (data.getNumberOfColumns() > 4) { - this.colFilter = 4; + function parseWeekday(input, locale) { + if (typeof input === 'string') { + if (!isNaN(input)) { + input = parseInt(input, 10); + } + else { + input = locale.weekdaysParse(input); + if (typeof input !== 'number') { + return null; + } + } + } + return input; } - } - else { - throw 'Unknown style "' + this.style + '"'; - } - }; - Graph3d.prototype.getNumberOfRows = function(data) { - return data.length; - } + /************************************ + Relative Time + ************************************/ - Graph3d.prototype.getNumberOfColumns = function(data) { - var counter = 0; - for (var column in data[0]) { - if (data[0].hasOwnProperty(column)) { - counter++; + // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize + function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) { + return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture); } - } - return counter; - } + function relativeTime(posNegDuration, withoutSuffix, locale) { + var duration = moment.duration(posNegDuration).abs(), + seconds = round(duration.as('s')), + minutes = round(duration.as('m')), + hours = round(duration.as('h')), + days = round(duration.as('d')), + months = round(duration.as('M')), + years = round(duration.as('y')), + + 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.d && ['dd', days] || + months === 1 && ['M'] || + months < relativeTimeThresholds.M && ['MM', months] || + years === 1 && ['y'] || ['yy', years]; - 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]); + args[2] = withoutSuffix; + args[3] = +posNegDuration > 0; + args[4] = locale; + return substituteTimeAgo.apply({}, args); } - } - return distinctValues; - } - 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; - }; + /************************************ + Week of Year + ************************************/ - /** - * 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; - // unsubscribe from the dataTable - if (this.dataSet) { - this.dataSet.off('*', this._onChange); - } + // 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 (rawData === undefined) - return; - if (Array.isArray(rawData)) { - rawData = new DataSet(rawData); - } + if (daysToDayOfWeek > end) { + daysToDayOfWeek -= 7; + } - var data; - if (rawData instanceof DataSet || rawData instanceof DataView) { - data = rawData.get(); - } - else { - throw new Error('Array, DataSet, or DataView expected'); - } + if (daysToDayOfWeek < end - 7) { + daysToDayOfWeek += 7; + } - if (data.length == 0) - return; + adjustedMoment = moment(mom).add(daysToDayOfWeek, 'd'); + return { + week: Math.ceil(adjustedMoment.dayOfYear() / 7), + year: adjustedMoment.year() + }; + } - this.dataSet = rawData; - this.dataTable = data; + //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; - // subscribe to changes in the dataset - this._onChange = function () { - me.setData(me.dataSet); - }; - this.dataSet.on('*', this._onChange); + 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; - // _determineColumnIndexes - // getNumberOfRows (points) - // getNumberOfColumns (x,y,z,v,t,t1,t2...) - // getDistinctValues (unique values?) - // getColumnRange + return { + year: dayOfYear > 0 ? year : year - 1, + dayOfYear: dayOfYear > 0 ? dayOfYear : daysInYear(year - 1) + dayOfYear + }; + } - // 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'; + /************************************ + Top Level Functions + ************************************/ + function makeMoment(config) { + var input = config._i, + format = config._f, + res; + config._locale = config._locale || moment.localeData(config._l); - // 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();}); - } - } + if (input === null || (format === undefined && input === '')) { + return moment.invalid({nullInput: true}); + } + if (typeof input === 'string') { + config._i = input = config._locale.preparse(input); + } - var withBars = this.style == Graph3d.STYLE.BAR || - this.style == Graph3d.STYLE.BARCOLOR || - this.style == Graph3d.STYLE.BARSIZE; + if (moment.isMoment(input)) { + return new Moment(input, true); + } else if (format) { + if (isArray(format)) { + makeDateFromStringAndArray(config); + } else { + makeDateFromStringAndFormat(config); + } + } else { + makeDateFromInput(config); + } - // 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; - } + res = new Moment(config); + if (res._nextDay) { + // Adding is smart enough around DST + res.add(1, 'd'); + res._nextDay = undefined; + } - if (this.defaultYBarWidth !== undefined) { - this.yBarWidth = this.defaultYBarWidth; - } - else { - var dataY = this.getDistinctValues(data,this.colY); - this.yBarWidth = (dataY[1] - dataY[0]) || 1; + return res; } - } - // 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 = function (input, format, locale, strict) { + var c; - var yRange = this.getColumnRange(data,this.colY); - if (withBars) { - yRange.min -= this.yBarWidth / 2; - yRange.max += this.yBarWidth / 2; - } - this.yMin = (this.defaultYMin !== undefined) ? this.defaultYMin : yRange.min; - this.yMax = (this.defaultYMax !== undefined) ? this.defaultYMax : yRange.max; - if (this.yMax <= this.yMin) this.yMax = this.yMin + 1; - this.yStep = (this.defaultYStep !== undefined) ? this.defaultYStep : (this.yMax-this.yMin)/5; + if (typeof(locale) === 'boolean') { + strict = locale; + locale = 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 = locale; + c._strict = strict; + c._isUTC = false; + c._pf = defaultParsingFlags(); - 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; + return makeMoment(c); + }; - 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.suppressDeprecationWarnings = false; - // set the scale dependent on the ranges. - this._setScale(); - }; + 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 + (config._useUTC ? ' UTC' : '')); + } + ); + // 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); - /** - * 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; + return pickBy('isBefore', args); + }; - var dataPoints = []; + moment.max = function () { + var args = [].slice.call(arguments, 0); - 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 + return pickBy('isAfter', args); + }; - // 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; + // creating with utc + moment.utc = function (input, format, locale, strict) { + var c; - if (dataX.indexOf(x) === -1) { - dataX.push(x); - } - if (dataY.indexOf(y) === -1) { - dataY.push(y); - } - } + if (typeof(locale) === 'boolean') { + strict = locale; + locale = 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 = locale; + c._i = input; + c._f = format; + c._strict = strict; + c._pf = defaultParsingFlags(); - var sortNumber = function (a, b) { - return a - b; + return makeMoment(c).utc(); }; - 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] = []; - } + // creating with unix timestamp (in seconds) + moment.unix = function (input) { + return moment(input * 1000); + }; - var point3d = new Point3d(); - point3d.x = x; - point3d.y = y; - point3d.z = z; + // duration + moment.duration = function (input, key) { + var duration = input, + // matching against regexp is expensive, do it on demand + match = null, + sign, + ret, + parseIso, + diffRes; - obj = {}; - obj.point = point3d; - obj.trans = undefined; - obj.screen = undefined; - obj.bottom = new Point3d(x, y, this.zMin); + 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]) + }; + } else if (duration == null) {// checks for null or undefined + duration = {}; + } else if (typeof duration === 'object' && + ('from' in duration || 'to' in duration)) { + diffRes = momentsDifference(moment(duration.from), moment(duration.to)); - dataMatrix[xIndex][yIndex] = obj; + duration = {}; + duration.ms = diffRes.milliseconds; + duration.M = diffRes.months; + } - dataPoints.push(obj); - } + ret = new Duration(duration); - // 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; + if (moment.isDuration(input) && hasOwnProp(input, '_locale')) { + ret._locale = input._locale; } - } - } - } - 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; + return ret; + }; - dataPoints.push(obj); - } - } + // version number + moment.version = VERSION; - return dataPoints; - }; + // default format + moment.defaultFormat = isoFormat; - /** - * 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); - } + // constant that refers to the ISO standard + moment.ISO_8601 = function () {}; - this.frame = document.createElement('div'); - this.frame.style.position = 'relative'; - this.frame.style.overflow = 'hidden'; + // Plugins that add properties should also add the key here (null value), + // so we can properly clone ourselves. + moment.momentProperties = momentProperties; - // 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 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.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); + // This function allows you to set a threshold for relative time strings + moment.relativeTimeThreshold = function (threshold, limit) { + if (relativeTimeThresholds[threshold] === undefined) { + return false; + } + if (limit === undefined) { + return relativeTimeThresholds[threshold]; + } + relativeTimeThresholds[threshold] = limit; + return true; + }; - // 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' + moment.lang = deprecate( + 'moment.lang is deprecated. Use moment.locale instead.', + function (key, value) { + return moment.locale(key, value); + } + ); - 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); + // This function will load locale and then set the global locale. If + // no arguments are passed in, it will simply return the current global + // locale key. + moment.locale = function (key, values) { + var data; + if (key) { + if (typeof(values) !== 'undefined') { + data = moment.defineLocale(key, values); + } + else { + data = moment.localeData(key); + } - // add the new graph to the container element - this.containerElement.appendChild(this.frame); - }; + if (data) { + moment.duration._locale = moment._locale = data; + } + } + return moment._locale._abbr; + }; - /** - * 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; + moment.defineLocale = function (name, values) { + if (values !== null) { + values.abbr = name; + if (!locales[name]) { + locales[name] = new Locale(); + } + locales[name].set(values); - this._resizeCanvas(); - }; + // backwards compat for now: also set the locale + moment.locale(name); - /** - * 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%'; + return locales[name]; + } else { + // useful for testing + delete locales[name]; + return null; + } + }; - this.frame.canvas.width = this.frame.canvas.clientWidth; - this.frame.canvas.height = this.frame.canvas.clientHeight; + moment.langData = deprecate( + 'moment.langData is deprecated. Use moment.localeData instead.', + function (key) { + return moment.localeData(key); + } + ); - // adjust with for margin - this.frame.filter.style.width = (this.frame.canvas.clientWidth - 2 * 10) + 'px'; - }; + // returns locale data + moment.localeData = function (key) { + var locale; - /** - * Start animation - */ - Graph3d.prototype.animationStart = function() { - if (!this.frame.filter || !this.frame.filter.slider) - throw 'No animation available'; + if (key && key._locale && key._locale._abbr) { + key = key._locale._abbr; + } - this.frame.filter.slider.play(); - }; + if (!key) { + return moment._locale; + } + if (!isArray(key)) { + //short-circuit everything else + locale = loadLocale(key); + if (locale) { + return locale; + } + key = [key]; + } - /** - * Stop animation - */ - Graph3d.prototype.animationStop = function() { - if (!this.frame.filter || !this.frame.filter.slider) return; + return chooseLocale(key); + }; - this.frame.filter.slider.stop(); - }; + // compare moment object + moment.isMoment = function (obj) { + return obj instanceof Moment || + (obj != null && hasOwnProp(obj, '_isAMomentObject')); + }; + // for typechecking Duration objects + moment.isDuration = function (obj) { + return obj instanceof Duration; + }; - /** - * 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 - } + for (i = lists.length - 1; i >= 0; --i) { + makeList(lists[i]); + } - // 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 - } - }; + moment.normalizeUnits = function (units) { + return normalizeUnits(units); + }; - /** - * 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; - } + moment.invalid = function (flags) { + var m = moment.utc(NaN); + if (flags != null) { + extend(m._pf, flags); + } + else { + m._pf.userInvalidated = true; + } - if (pos.horizontal !== undefined && pos.vertical !== undefined) { - this.camera.setArmRotation(pos.horizontal, pos.vertical); - } + return m; + }; - if (pos.distance !== undefined) { - this.camera.setArmLength(pos.distance); - } + moment.parseZone = function () { + return moment.apply(null, arguments).parseZone(); + }; - this.redraw(); - }; + moment.parseTwoDigitYear = function (input) { + return toInt(input) + (toInt(input) > 68 ? 1900 : 2000); + }; + moment.isDate = isDate; - /** - * 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; - }; - - /** - * Load data into the 3D Graph - */ - Graph3d.prototype._readData = function(data) { - // read the data - this._dataInitialize(data, this.style); - - - if (this.dataFilter) { - // apply filtering - this.dataPoints = this.dataFilter._getDataPoints(); - } - else { - // no filtering. load all data - this.dataPoints = this._getDataPoints(this.dataTable); - } - - // draw the filter - this._redrawFilter(); - }; - - /** - * 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(); - } - }; - - /** - * Update the options. Options will be merged with current options - * @param {Object} options - */ - Graph3d.prototype.setOptions = function (options) { - var cameraPosition = undefined; + /************************************ + Moment Prototype + ************************************/ - this.animationStop(); - if (options !== undefined) { - // retrieve parameter values - if (options.width !== undefined) this.width = options.width; - if (options.height !== undefined) this.height = options.height; + extend(moment.fn = Moment.prototype, { - if (options.xCenter !== undefined) this.defaultXCenter = options.xCenter; - if (options.yCenter !== undefined) this.defaultYCenter = options.yCenter; + clone : function () { + return moment(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; + valueOf : function () { + return +this._d - ((this._offset || 0) * 60000); + }, - if (options.xValueLabel !== undefined) this.xValueLabel = options.xValueLabel; - if (options.yValueLabel !== undefined) this.yValueLabel = options.yValueLabel; - if (options.zValueLabel !== undefined) this.zValueLabel = options.zValueLabel; + unix : function () { + return Math.floor(+this / 1000); + }, - 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; + toString : function () { + return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ'); + }, - if (options.animationInterval !== undefined) this.animationInterval = options.animationInterval; - if (options.animationPreload !== undefined) this.animationPreload = options.animationPreload; - if (options.animationAutoStart !== undefined)this.animationAutoStart = options.animationAutoStart; + toDate : function () { + return this._offset ? new Date(+this) : this._d; + }, - if (options.xBarWidth !== undefined) this.defaultXBarWidth = options.xBarWidth; - if (options.yBarWidth !== undefined) this.defaultYBarWidth = options.yBarWidth; + toISOString : function () { + var m = moment(this).utc(); + if (0 < m.year() && m.year() <= 9999) { + if ('function' === typeof Date.prototype.toISOString) { + // native implementation is ~50x faster, use it when we can + return this.toDate().toISOString(); + } else { + 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]'); + } + }, - 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; + toArray : function () { + var m = this; + return [ + m.year(), + m.month(), + m.date(), + m.hours(), + m.minutes(), + m.seconds(), + m.milliseconds() + ]; + }, - if (options.cameraPosition !== undefined) cameraPosition = options.cameraPosition; + isValid : function () { + return isValid(this); + }, - 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); - } - } + isDSTShifted : function () { + if (this._a) { + return this.isValid() && compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()) > 0; + } - this._setBackgroundColor(options && options.backgroundColor); + return false; + }, - this.setSize(this.width, this.height); + parsingFlags : function () { + return extend({}, this._pf); + }, - // re-load the data - if (this.dataTable) { - this.setData(this.dataTable); - } + invalidAt: function () { + return this._pf.overflow; + }, - // start animation when option is true - if (this.animationAutoStart && this.dataFilter) { - this.animationStart(); - } - }; + utc : function (keepLocalTime) { + return this.utcOffset(0, keepLocalTime); + }, - /** - * Redraw the Graph. - */ - Graph3d.prototype.redraw = function() { - if (this.dataPoints === undefined) { - throw 'Error: graph data not initialized'; - } + local : function (keepLocalTime) { + if (this._isUTC) { + this.utcOffset(0, keepLocalTime); + this._isUTC = false; - this._resizeCanvas(); - this._resizeCenter(); - this._redrawSlider(); - this._redrawClear(); - this._redrawAxis(); + if (keepLocalTime) { + this.subtract(this._dateUtcOffset(), 'm'); + } + } + return this; + }, - 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(); - } + format : function (inputString) { + var output = formatMoment(this, inputString || moment.defaultFormat); + return this.localeData().postformat(output); + }, - this._redrawInfo(); - this._redrawLegend(); - }; + add : createAdder(1, 'add'), - /** - * Clear the canvas before redrawing - */ - Graph3d.prototype._redrawClear = function() { - var canvas = this.frame.canvas; - var ctx = canvas.getContext('2d'); + subtract : createAdder(-1, 'subtract'), - ctx.clearRect(0, 0, canvas.width, canvas.height); - }; + diff : function (input, units, asFloat) { + var that = makeAs(input, this), + zoneDiff = (that.utcOffset() - this.utcOffset()) * 6e4, + anchor, diff, output, daysAdjust; + units = normalizeUnits(units); - /** - * Redraw the legend showing the colors - */ - Graph3d.prototype._redrawLegend = function() { - var y; + if (units === 'year' || units === 'month' || units === 'quarter') { + output = monthDiff(this, that); + if (units === 'quarter') { + output = output / 3; + } else 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); + }, - if (this.style === Graph3d.STYLE.DOTCOLOR || - this.style === Graph3d.STYLE.DOTSIZE) { + from : function (time, withoutSuffix) { + return moment.duration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix); + }, - var dotSize = this.frame.clientWidth * 0.02; + fromNow : function (withoutSuffix) { + return this.from(moment(), withoutSuffix); + }, - 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 - } + calendar : function (time) { + // We want to compare the start of today, vs this. + // Getting start-of-today depends on whether we're locat/utc/offset + // 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.localeData().calendar(format, this, moment(now))); + }, - 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; - } + isLeapYear : function () { + return isLeapYear(this.year()); + }, - var canvas = this.frame.canvas; - var ctx = canvas.getContext('2d'); - ctx.lineWidth = 1; - ctx.font = '14px arial'; // TODO: put in options + isDST : function () { + return (this.utcOffset() > this.clone().month(0).utcOffset() || + this.utcOffset() > this.clone().month(5).utcOffset()); + }, - 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); + day : function (input) { + var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay(); + if (input != null) { + input = parseWeekday(input, this.localeData()); + return this.add(input - day, 'd'); + } else { + return day; + } + }, - //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); + month : makeAccessor('Month', true), - ctx.strokeStyle = color; - ctx.beginPath(); - ctx.moveTo(left, top + y); - ctx.lineTo(right, top + y); - ctx.stroke(); - } + 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 */ + } - ctx.strokeStyle = this.colorAxis; - ctx.strokeRect(left, top, widthMax, height); - } + // weeks are a special case + if (units === 'week') { + this.weekday(0); + } else if (units === 'isoWeek') { + this.isoWeekday(1); + } - 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(); - } + // quarters are also special + if (units === 'quarter') { + this.month(Math.floor(this.month() / 3) * 3); + } - 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(); + endOf: function (units) { + units = normalizeUnits(units); + if (units === undefined || units === 'millisecond') { + return this; + } + return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms'); + }, - ctx.textAlign = 'right'; - ctx.textBaseline = 'middle'; - ctx.fillStyle = this.colorAxis; - ctx.fillText(step.getCurrent(), left - 2 * gridLineLen, y); + isAfter: function (input, units) { + var inputMs; + units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond'); + if (units === 'millisecond') { + input = moment.isMoment(input) ? input : moment(input); + return +this > +input; + } else { + inputMs = moment.isMoment(input) ? +input : +moment(input); + return inputMs < +this.clone().startOf(units); + } + }, - step.next(); - } + isBefore: function (input, units) { + var inputMs; + units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond'); + if (units === 'millisecond') { + input = moment.isMoment(input) ? input : moment(input); + return +this < +input; + } else { + inputMs = moment.isMoment(input) ? +input : +moment(input); + return +this.clone().endOf(units) < inputMs; + } + }, - ctx.textAlign = 'right'; - ctx.textBaseline = 'top'; - var label = this.legendLabel; - ctx.fillText(label, right, bottom + this.margin); - } - }; + isBetween: function (from, to, units) { + return this.isAfter(from, units) && this.isBefore(to, units); + }, - /** - * Redraw the filter - */ - Graph3d.prototype._redrawFilter = function() { - this.frame.filter.innerHTML = ''; + isSame: function (input, units) { + var inputMs; + units = normalizeUnits(units || 'millisecond'); + if (units === 'millisecond') { + input = moment.isMoment(input) ? input : moment(input); + return +this === +input; + } else { + inputMs = +moment(input); + return +(this.clone().startOf(units)) <= inputMs && inputMs <= +(this.clone().endOf(units)); + } + }, - if (this.dataFilter) { - var options = { - 'visible': this.showAnimationControls - }; - var slider = new Slider(this.frame.filter, options); - this.frame.filter.slider = slider; + 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; + } + ), - // TODO: css here is not nice here... - this.frame.filter.style.padding = '10px'; - //this.frame.filter.style.backgroundColor = '#EFEFEF'; + 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; + } + ), - slider.setValues(this.dataFilter.values); - slider.setPlayInterval(this.animationInterval); + zone : deprecate( + 'moment().zone is deprecated, use moment().utcOffset instead. ' + + 'https://github.com/moment/moment/issues/1779', + function (input, keepLocalTime) { + if (input != null) { + if (typeof input !== 'string') { + input = -input; + } - // create an event handler - var me = this; - var onchange = function () { - var index = slider.getIndex(); + this.utcOffset(input, keepLocalTime); - me.dataFilter.selectValue(index); - me.dataPoints = me.dataFilter._getDataPoints(); + return this; + } else { + return -this.utcOffset(); + } + } + ), - me.redraw(); - }; - slider.setOnChangeCallback(onchange); - } - else { - this.frame.filter.slider = undefined; - } - }; - - /** - * Redraw the slider - */ - Graph3d.prototype._redrawSlider = function() { - if ( this.frame.filter.slider !== undefined) { - this.frame.filter.slider.redraw(); - } - }; - - - /** - * Redraw common information - */ - Graph3d.prototype._redrawInfo = function() { - if (this.dataFilter) { - var canvas = this.frame.canvas; - var ctx = canvas.getContext('2d'); + // keepLocalTime = true means only change the timezone, without + // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]--> + // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset + // +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. + utcOffset : function (input, keepLocalTime) { + var offset = this._offset || 0, + localAdjust; + if (input != null) { + if (typeof input === 'string') { + input = utcOffsetFromString(input); + } + if (Math.abs(input) < 16) { + input = input * 60; + } + if (!this._isUTC && keepLocalTime) { + localAdjust = this._dateUtcOffset(); + } + this._offset = input; + this._isUTC = true; + if (localAdjust != null) { + this.add(localAdjust, 'm'); + } + if (offset !== input) { + if (!keepLocalTime || this._changeInProgress) { + addOrSubtractDurationFromMoment(this, + moment.duration(input - offset, 'm'), 1, false); + } else if (!this._changeInProgress) { + this._changeInProgress = true; + moment.updateOffset(this, true); + this._changeInProgress = null; + } + } - ctx.font = '14px arial'; // TODO: put in options - ctx.lineStyle = 'gray'; - ctx.fillStyle = 'gray'; - ctx.textAlign = 'left'; - ctx.textBaseline = 'top'; + return this; + } else { + return this._isUTC ? offset : this._dateUtcOffset(); + } + }, - var x = this.margin; - var y = this.margin; - ctx.fillText(this.dataFilter.getLabel() + ': ' + this.dataFilter.getSelectedValue(), x, y); - } - }; + isLocal : function () { + return !this._isUTC; + }, + isUtcOffset : function () { + return this._isUTC; + }, - /** - * 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; + isUtc : function () { + return this._isUTC && this._offset === 0; + }, - // TODO: get the actual rendered style of the containerElement - //ctx.font = this.containerElement.style.font; - ctx.font = 24 / this.camera.getArmLength() + 'px arial'; + zoneAbbr : function () { + return this._isUTC ? 'UTC' : ''; + }, - // 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; + zoneName : function () { + return this._isUTC ? 'Coordinated Universal Time' : ''; + }, - // 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(); + parseZone : function () { + if (this._tzm) { + this.utcOffset(this._tzm); + } else if (typeof this._i === 'string') { + this.utcOffset(utcOffsetFromString(this._i)); + } + return this; + }, - 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(); + hasAlignedHourOffset : function (input) { + if (!input) { + input = 0; + } + else { + input = moment(input).utcOffset(); + } - 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(); - } + return (this.utcOffset() - input) % 60 === 0; + }, - 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'; - } - ctx.fillStyle = this.colorAxis; - ctx.fillText(' ' + this.xValueLabel(step.getCurrent()) + ' ', text.x, text.y); + daysInMonth : function () { + return daysInMonth(this.year(), this.month()); + }, - step.next(); - } + dayOfYear : function (input) { + var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1; + return input == null ? dayOfYear : this.add((input - dayOfYear), 'd'); + }, - // 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(); + quarter : function (input) { + return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3); + }, - 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(); - } + weekYear : function (input) { + var year = weekOfYear(this, this.localeData()._week.dow, this.localeData()._week.doy).year; + return input == null ? year : this.add((input - year), 'y'); + }, - 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(' ' + this.yValueLabel(step.getCurrent()) + ' ', text.x, text.y); + isoWeekYear : function (input) { + var year = weekOfYear(this, 1, 4).year; + return input == null ? year : this.add((input - year), 'y'); + }, - step.next(); - } + week : function (input) { + var week = this.localeData().week(this); + return input == null ? week : this.add((input - week) * 7, 'd'); + }, - // 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(); - } - 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(); + isoWeek : function (input) { + var week = weekOfYear(this, 1, 4).week; + return input == null ? week : this.add((input - week) * 7, 'd'); + }, - ctx.textAlign = 'right'; - ctx.textBaseline = 'middle'; - ctx.fillStyle = this.colorAxis; - ctx.fillText(this.zValueLabel(step.getCurrent()) + ' ', from.x - 5, from.y); + weekday : function (input) { + var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7; + return input == null ? weekday : this.add(input - weekday, 'd'); + }, - 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(); + 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); + }, - // 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(); + isoWeeksInYear : function () { + return weeksInYear(this.year(), 1, 4); + }, - // 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(); + weeksInYear : function () { + var weekInfo = this.localeData()._week; + return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy); + }, - // 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); - } + get : function (units) { + units = normalizeUnits(units); + return this[units](); + }, - // 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 : function (units, value) { + var unit; + if (typeof units === 'object') { + for (unit in units) { + this.set(unit, units[unit]); + } + } + else { + units = normalizeUnits(units); + if (typeof this[units] === 'function') { + this[units](value); + } + } + return this; + }, - // 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); - } - }; + // If passed a locale key, it will set the locale for this + // instance. Otherwise, it will return the locale configuration + // variables for this instance. + locale : function (key) { + var newLocaleData; - /** - * 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 - */ - Graph3d.prototype._hsv2rgb = function(H, S, V) { - var R, G, B, C, Hi, X; + if (key === undefined) { + return this._locale._abbr; + } else { + newLocaleData = moment.localeData(key); + if (newLocaleData != null) { + this._locale = newLocaleData; + } + return this; + } + }, - C = V * S; - Hi = Math.floor(H/60); // hi = 0,1,2,3,4,5 - X = C * (1 - Math.abs(((H/60) % 2) - 1)); + lang : deprecate( + 'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.', + function (key) { + if (key === undefined) { + return this.localeData(); + } else { + return this.locale(key); + } + } + ), - 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; + localeData : function () { + return this._locale; + }, - default: R = 0; G = 0; B = 0; break; - } + _dateUtcOffset : function () { + // On Firefox.24 Date#getTimezoneOffset returns a floating point. + // https://github.com/moment/moment/pull/1871 + return -Math.round(this._d.getTimezoneOffset() / 15) * 15; + } - return 'RGB(' + parseInt(R*255) + ',' + parseInt(G*255) + ',' + parseInt(B*255) + ')'; - }; + }); + function rawMonthSetter(mom, value) { + var dayOfMonth; - /** - * Draw all datapoints as a grid - * This function can be used when the style is 'grid' - */ - 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; + // TODO: Move this out of here! + if (typeof value === 'string') { + value = mom.localeData().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; + } - if (this.dataPoints === undefined || this.dataPoints.length <= 0) - return; // TODO: throw exception? + function rawGetter(mom, unit) { + return mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit](); + } - // 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; + function rawSetter(mom, unit, value) { + if (unit === 'Month') { + return rawMonthSetter(mom, value); + } else { + return mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value); + } + } - // 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; - } + 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); + } + }; + } - // sort the points on depth of their (x,y) position (not on z) - var sortDepth = function (a, b) { - return b.dist - a.dist; - }; - this.dataPoints.sort(sortDepth); + moment.fn.millisecond = moment.fn.milliseconds = makeAccessor('Milliseconds', false); + moment.fn.second = moment.fn.seconds = makeAccessor('Seconds', false); + moment.fn.minute = moment.fn.minutes = makeAccessor('Minutes', false); + // Setting the hour should keep the time, because the user explicitly + // specified which hour he wants. So trying to maintain the same hour (in + // a new timezone) makes sense. Adding/subtracting hours does not follow + // this rule. + moment.fn.hour = moment.fn.hours = makeAccessor('Hours', true); + // moment.fn.month is defined separately + moment.fn.date = makeAccessor('Date', true); + moment.fn.dates = deprecate('dates accessor is deprecated. Use date instead.', makeAccessor('Date', true)); + moment.fn.year = makeAccessor('FullYear', true); + moment.fn.years = deprecate('years accessor is deprecated. Use year instead.', makeAccessor('FullYear', true)); - if (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; + // 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; - if (point !== undefined && right !== undefined && top !== undefined && cross !== undefined) { + // add aliased format methods + moment.fn.toJSON = moment.fn.toISOString; - 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) + // alias isUtc for dev-friendliness + moment.fn.isUTC = moment.fn.isUtc; - topSideVisible = (crossproduct.z > 0); - } - else { - topSideVisible = true; - } + /************************************ + Duration Prototype + ************************************/ - 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; + function daysToYears (days) { + // 400 years have 146097 days (taking into account leap year rules) + return days * 400 / 146097; + } - 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(); - } + function yearsToDays (years) { + // years * 365 + absRound(years / 4) - + // absRound(years / 100) + absRound(years / 400); + return years * 146097 / 400; } - } - else { // grid style - for (i = 0; i < this.dataPoints.length; i++) { - point = this.dataPoints[i]; - right = this.dataPoints[i].pointRight; - top = this.dataPoints[i].pointTop; - if (point !== undefined) { - if (this.showPerspective) { - lineWidth = 2 / -point.trans.z; - } - else { - lineWidth = 2 * -(this.eye.z / this.camera.getArmLength()); - } - } + extend(moment.duration.fn = Duration.prototype, { - 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; + _bubble : function () { + var milliseconds = this._milliseconds, + days = this._days, + months = this._months, + data = this._data, + seconds, minutes, hours, years = 0; - 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(); - } + // The following code bubbles up values, see the tests for + // examples of what that means. + data.milliseconds = milliseconds % 1000; - 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; + seconds = absRound(milliseconds / 1000); + data.seconds = seconds % 60; - 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(); - } - } - } - }; + minutes = absRound(seconds / 60); + data.minutes = minutes % 60; + hours = absRound(minutes / 60); + data.hours = hours % 24; - /** - * Draw all datapoints as dots. - * This function can be used when the style is 'dot' or 'dot-line' - */ - Graph3d.prototype._redrawDataDot = function() { - var canvas = this.frame.canvas; - var ctx = canvas.getContext('2d'); - var i; + days += absRound(hours / 24); - if (this.dataPoints === undefined || this.dataPoints.length <= 0) - return; // TODO: throw exception? + // Accurately convert days to years, assume start from year 0. + years = absRound(daysToYears(days)); + days -= absRound(yearsToDays(years)); - // 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; + // 30 days to a month + // TODO (iskren): Use anchor date (like 1st Jan) to compute this. + months += absRound(days / 30); + days %= 30; - // 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; - } + // 12 months -> 1 year + years += absRound(months / 12); + months %= 12; - // order the translated points by depth - var sortDepth = function (a, b) { - return b.dist - a.dist; - }; - this.dataPoints.sort(sortDepth); + data.days = days; + data.months = months; + data.years = years; + }, - // 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]; + abs : function () { + this._milliseconds = Math.abs(this._milliseconds); + this._days = Math.abs(this._days); + this._months = Math.abs(this._months); - 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(); - } + this._data.milliseconds = Math.abs(this._data.milliseconds); + this._data.seconds = Math.abs(this._data.seconds); + this._data.minutes = Math.abs(this._data.minutes); + this._data.hours = Math.abs(this._data.hours); + this._data.months = Math.abs(this._data.months); + this._data.years = Math.abs(this._data.years); - // 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; - } + return this; + }, - var radius; - if (this.showPerspective) { - radius = size / -point.trans.z; - } - else { - radius = size * -(this.eye.z / this.camera.getArmLength()); - } - if (radius < 0) { - radius = 0; - } + weeks : function () { + return absRound(this.days() / 7); + }, - 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); - } + valueOf : function () { + return this._milliseconds + + this._days * 864e5 + + (this._months % 12) * 2592e6 + + toInt(this._months / 12) * 31536e6; + }, - // 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(); - } - }; + humanize : function (withSuffix) { + var output = relativeTime(this, !withSuffix, this.localeData()); - /** - * Draw all datapoints as bars. - * This function can be used when the style is 'bar', 'bar-color', or 'bar-size' - */ - Graph3d.prototype._redrawDataBar = function() { - var canvas = this.frame.canvas; - var ctx = canvas.getContext('2d'); - var i, j, surface, corners; + if (withSuffix) { + output = this.localeData().pastFuture(+this, output); + } - if (this.dataPoints === undefined || this.dataPoints.length <= 0) - return; // TODO: throw exception? + return this.localeData().postformat(output); + }, - // 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; + add : function (input, val) { + // supports only 2.0-style add(1, 's') or add(moment) + var dur = moment.duration(input, val); - // 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; - } + this._milliseconds += dur._milliseconds; + this._days += dur._days; + this._months += dur._months; - // order the translated points by depth - var sortDepth = function (a, b) { - return b.dist - a.dist; - }; - this.dataPoints.sort(sortDepth); + this._bubble(); - // 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]; + return this; + }, - // 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); - } + subtract : function (input, val) { + var dur = moment.duration(input, val); - // 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); - } + this._milliseconds -= dur._milliseconds; + this._days -= dur._days; + this._months -= dur._months; - // 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)} - ]; + this._bubble(); - // 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); - }); + return this; + }, - // 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; + get : function (units) { + units = normalizeUnits(units); + return this[units.toLowerCase() + 's'](); + }, - // 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}) - } + as : function (units) { + var days, months; + units = normalizeUnits(units); - // order the surfaces by their (translated) depth - surfaces.sort(function (a, b) { - var diff = b.dist - a.dist; - if (diff) return diff; + if (units === 'month' || units === 'year') { + days = this._days + this._milliseconds / 864e5; + months = this._months + daysToYears(days) * 12; + return units === 'month' ? months : months / 12; + } else { + // handle milliseconds separately because of floating point math errors (issue #1867) + days = this._days + Math.round(yearsToDays(this._months / 12)); + switch (units) { + case 'week': return days / 7 + this._milliseconds / 6048e5; + case 'day': return days + this._milliseconds / 864e5; + case 'hour': return days * 24 + this._milliseconds / 36e5; + case 'minute': return days * 24 * 60 + this._milliseconds / 6e4; + case 'second': return days * 24 * 60 * 60 + this._milliseconds / 1000; + // Math.floor prevents floating point math errors here + case 'millisecond': return Math.floor(days * 24 * 60 * 60 * 1000) + this._milliseconds; + default: throw new Error('Unknown unit ' + units); + } + } + }, - // if equal depth, sort the top surface last - if (a.corners === top) return 1; - if (b.corners === top) return -1; + lang : moment.fn.lang, + locale : moment.fn.locale, - // both are equal - return 0; - }); + toIsoString : deprecate( + 'toIsoString() is deprecated. Please use toISOString() instead ' + + '(notice the capitals)', + function () { + return this.toISOString(); + } + ), - // 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(); - } - } - }; + 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'; + } - /** - * Draw a line through all datapoints. - * This function can be used when the style is 'line' - */ - Graph3d.prototype._redrawDataLine = function() { - var canvas = this.frame.canvas, - ctx = canvas.getContext('2d'), - point, i; + 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' : ''); + }, - 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); + localeData : function () { + return this._locale; + }, - this.dataPoints[i].trans = trans; - this.dataPoints[i].screen = screen; - } + toJSON : function () { + return this.toISOString(); + } + }); - // start the line - if (this.dataPoints.length > 0) { - point = this.dataPoints[0]; + moment.duration.fn.toString = moment.duration.fn.toISOString; - ctx.lineWidth = 1; // TODO: make customizable - ctx.strokeStyle = 'blue'; // TODO: make customizable - ctx.beginPath(); - ctx.moveTo(point.screen.x, point.screen.y); - } + function makeDurationGetter(name) { + moment.duration.fn[name] = function () { + return this._data[name]; + }; + } - // 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); - } + for (i in unitMillisecondFactors) { + if (hasOwnProp(unitMillisecondFactors, i)) { + makeDurationGetter(i.toLowerCase()); + } + } - // finish the line - if (this.dataPoints.length > 0) { - ctx.stroke(); - } - }; + moment.duration.fn.asMilliseconds = function () { + return this.as('ms'); + }; + moment.duration.fn.asSeconds = function () { + return this.as('s'); + }; + moment.duration.fn.asMinutes = function () { + return this.as('m'); + }; + moment.duration.fn.asHours = function () { + return this.as('h'); + }; + moment.duration.fn.asDays = function () { + return this.as('d'); + }; + moment.duration.fn.asWeeks = function () { + return this.as('weeks'); + }; + moment.duration.fn.asMonths = function () { + return this.as('M'); + }; + moment.duration.fn.asYears = function () { + return this.as('y'); + }; - /** - * Start a moving operation inside the provided parent element - * @param {Event} event The event that occurred (required for - * retrieving the mouse position) - */ - Graph3d.prototype._onMouseDown = function(event) { - event = event || window.event; + /************************************ + Default Locale + ************************************/ - // 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; + // Set default locale, other locale will inherit from English. + moment.locale('en', { + ordinalParse: /\d{1,2}(th|st|nd|rd)/, + 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; + } + }); - // get mouse position (different code for IE and all other browsers) - this.startMouseX = getMouseX(event); - this.startMouseY = getMouseY(event); + /* EMBED_LOCALES */ - this.startStart = new Date(this.start); - this.startEnd = new Date(this.end); - this.startArmRotation = this.camera.getArmRotation(); + /************************************ + Exposing Moment + ************************************/ - this.frame.style.cursor = 'move'; + 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; + } + } - // 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); - }; + // 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))) - /** - * Perform moving operating. - * This function activated from within the funcion Graph.mouseDown(). - * @param {Event} event Well, eehh, the event - */ - Graph3d.prototype._onMouseMove = function (event) { - event = event || window.event; +/***/ }, +/* 4 */ +/***/ function(module, exports, __webpack_require__) { - // calculate change in mouse position - var diffX = parseFloat(getMouseX(event)) - this.startMouseX; - var diffY = parseFloat(getMouseY(event)) - this.startMouseY; + function webpackContext(req) { + throw new Error("Cannot find module '" + req + "'."); + } + webpackContext.keys = function() { return []; }; + webpackContext.resolve = webpackContext; + module.exports = webpackContext; + webpackContext.id = 4; - 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); +/***/ }, +/* 5 */ +/***/ function(module, exports, __webpack_require__) { - // snap horizontally to nice angles at 0pi, 0.5pi, 1pi, 1.5pi, etc... - // the -0.001 is to take care that the vertical axis is always drawn at the left front corner - if (Math.abs(Math.sin(horizontalNew)) < snapValue) { - horizontalNew = Math.round((horizontalNew / Math.PI)) * Math.PI - 0.001; - } - if (Math.abs(Math.cos(horizontalNew)) < snapValue) { - horizontalNew = (Math.round((horizontalNew/ Math.PI - 0.5)) + 0.5) * Math.PI - 0.001; - } + module.exports = function(module) { + if(!module.webpackPolyfill) { + module.deprecate = function() {}; + module.paths = []; + // module.parent = undefined by default + module.children = []; + module.webpackPolyfill = 1; + } + return module; + } - // snap vertically to nice angles - if (Math.abs(Math.sin(verticalNew)) < snapValue) { - verticalNew = Math.round((verticalNew / Math.PI)) * Math.PI; - } - if (Math.abs(Math.cos(verticalNew)) < snapValue) { - verticalNew = (Math.round((verticalNew/ Math.PI - 0.5)) + 0.5) * Math.PI; - } - this.camera.setArmRotation(horizontalNew, verticalNew); - this.redraw(); +/***/ }, +/* 6 */ +/***/ function(module, exports, __webpack_require__) { - // fire a cameraPositionChange event - var parameters = this.getCameraPosition(); - this.emit('cameraPositionChange', parameters); + // DOM utility methods - util.preventDefault(event); + /** + * 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 = []; + } + } }; - /** - * Stop moving operating. - * This function activated from within the funcion Graph.mouseDown(). - * @param {event} event The event + * 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 */ - Graph3d.prototype._onMouseUp = function (event) { - this.frame.style.cursor = 'auto'; - this.leftButtonDown = false; - - // remove event listeners here - util.removeEventListener(document, 'mousemove', this.onmousemove); - util.removeEventListener(document, 'mouseup', this.onmouseup); - util.preventDefault(event); + 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 = []; + } + } + } }; /** - * 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 + * 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 */ - Graph3d.prototype._onTooltip = function (event) { - var delay = 300; // ms - var boundingRect = this.frame.getBoundingClientRect(); - var mouseX = getMouseX(event) - boundingRect.left; - var mouseY = getMouseY(event) - boundingRect.top; - - if (!this.showTooltip) { - return; + 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); + } } - - if (this.tooltipTimeout) { - clearTimeout(this.tooltipTimeout); + 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; + }; - // (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); + /** + * 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, insertBefore) { + var element; + // allocate DOM element, if it doesnt yet exist, create one. + if (JSONcontainer.hasOwnProperty(elementType)) { // this element has been created before + // check if there is an redundant element + if (JSONcontainer[elementType].redundant.length > 0) { + element = JSONcontainer[elementType].redundant[0]; + JSONcontainer[elementType].redundant.shift(); + } + else { + // create a new element and add it to the SVG + element = document.createElement(elementType); + if (insertBefore !== undefined) { + DOMContainer.insertBefore(element, insertBefore); } else { - this._hideTooltip(); + DOMContainer.appendChild(element); } } } 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); + // 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: []}; + if (insertBefore !== undefined) { + DOMContainer.insertBefore(element, insertBefore); + } + else { + DOMContainer.appendChild(element); + } } + JSONcontainer[elementType].used.push(element); + return element; }; - /** - * Event handler for touchstart event on mobile devices - */ - 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); - }; - - /** - * Event handler for touchmove event on mobile devices - */ - Graph3d.prototype._onTouchMove = function(event) { - this._onMouseMove(event); - }; - - /** - * Event handler for touchend event on mobile devices - */ - Graph3d.prototype._onTouchEnd = function(event) { - this.touchDown = false; - - util.removeEventListener(document, 'touchmove', this.ontouchmove); - util.removeEventListener(document, 'touchend', this.ontouchend); - this._onMouseUp(event); - }; /** - * Event handler for mouse wheel event, used to zoom the graph - * Code from http://adomas.org/javascript-mouse-wheel/ - * @param {event} event The event + * 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 + * @param labelObj + * @returns {*} */ - 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; + exports.drawPoint = function(x, y, group, JSONcontainer, svgContainer, labelObj) { + 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); + } + 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); } - // 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); + if(group.options.drawPoints.styles !== undefined) { + point.setAttributeNS(null, "style", group.group.options.drawPoints.styles); + } + point.setAttributeNS(null, "class", group.className + " point"); + //handle label + var label = exports.getSVGElement('text',JSONcontainer,svgContainer); + if (labelObj){ + if (labelObj.xOffset) { + x = x + labelObj.xOffset; + } - this.camera.setArmLength(newLength); - this.redraw(); + if (labelObj.yOffset) { + y = y + labelObj.yOffset; + } + if (labelObj.content) { + label.textContent = labelObj.content; + } - this._hideTooltip(); - } + if (labelObj.className) { + label.setAttributeNS(null, "class", labelObj.className + " label"); + } - // fire a cameraPositionChange event - var parameters = this.getCameraPosition(); - this.emit('cameraPositionChange', parameters); - // Prevent default actions caused by mouse wheel. - // That might be ugly, but we handle scrolls somehow - // anyway, so don't bother here.. - util.preventDefault(event); + } + label.setAttributeNS(null, "x", x); + label.setAttributeNS(null, "y", y); + return point; }; /** - * 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 + * draw a bar SVG element centered on the X coordinate + * + * @param x + * @param y + * @param className */ - Graph3d.prototype._insideTriangle = function (point, triangle) { - var a = triangle[0], - b = triangle[1], - c = triangle[2]; - - function sign (x) { - return x > 0 ? 1 : x < 0 ? -1 : 0; + exports.drawBar = function (x, y, width, height, className, JSONcontainer, svgContainer) { + if (height != 0) { + if (height < 0) { + height *= -1; + y -= height; + } + var rect = exports.getSVGElement('rect',JSONcontainer, svgContainer); + rect.setAttributeNS(null, "x", x - 0.5 * width); + rect.setAttributeNS(null, "y", y); + rect.setAttributeNS(null, "width", width); + rect.setAttributeNS(null, "height", height); + rect.setAttributeNS(null, "class", className); } + }; - 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)); +/***/ }, +/* 7 */ +/***/ function(module, exports, __webpack_require__) { - // 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); - }; + var util = __webpack_require__(1); + var Queue = __webpack_require__(8); /** - * 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 + * + * 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; 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; - } - } - } - } + // TODO: add a DataSet constructor DataSet(data, options) + function DataSet (data, options) { + // correctly read optional arguments + if (data && !Array.isArray(data) && !util.isDataTable(data)) { + options = data; + data = null; } - 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; + this._options = options || {}; + this._data = {}; // map with data indexed by id + this.length = 0; // number of items in the DataSet + this._fieldId = this._options.fieldId || 'id'; // name of the field containing id + this._type = {}; // internal field types (NOTE: this can differ from this._options.type) + + // all variants of a Date are internally stored as Date, so we can convert + // from everything to everything (also from ISODate to Number for example) + if (this._options.type) { + for (var field in this._options.type) { + if (this._options.type.hasOwnProperty(field)) { + var value = this._options.type[field]; + if (value == 'Date' || value == 'ISODate' || value == 'ASPDate') { + this._type[field] = 'Date'; + } + else { + this._type[field] = value; } } } } - - return closestDataPoint; - }; - - /** - * Display a tooltip for given data point - * @param {Object} dataPoint - * @private - */ - 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 - } - }; - } - else { - content = this.tooltip.dom.content; - line = this.tooltip.dom.line; - dot = this.tooltip.dom.dot; + // 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.'); } - this._hideTooltip(); + this._subscribers = {}; // event subscribers - 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 + '
'; + // add initial data when provided + if (data) { + this.add(data); } - 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'; - }; + this.setOptions(options); + } /** - * Hide the tooltip when displayed - * @private + * @param {Object} [options] Available options: + * {Object} queue Queue changes to the DataSet, + * flush them all at once. + * Queue options: + * - {number} delay Delay in ms, null by default + * - {number} max Maximum number of entries in the queue, Infinity by default + * @param options */ - Graph3d.prototype._hideTooltip = function () { - if (this.tooltip) { - this.tooltip.dataPoint = null; + DataSet.prototype.setOptions = function(options) { + if (options && options.queue !== undefined) { + if (options.queue === false) { + // delete queue if loaded + if (this._queue) { + this._queue.destroy(); + delete this._queue; + } + } + else { + // create queue and update its options + if (!this._queue) { + this._queue = Queue.extend(this, { + replace: ['add', 'update', 'remove'] + }); + } - for (var prop in this.tooltip.dom) { - if (this.tooltip.dom.hasOwnProperty(prop)) { - var elem = this.tooltip.dom[prop]; - if (elem && elem.parentNode) { - elem.parentNode.removeChild(elem); - } + if (typeof options.queue === 'object') { + this._queue.setOptions(options.queue); } } } }; - /**--------------------------------------------------------------------------**/ - - /** - * Get the horizontal mouse position from a mouse event - * @param {Event} event - * @return {Number} mouse x - */ - function getMouseX (event) { - if ('clientX' in event) return event.clientX; - return event.targetTouches[0] && event.targetTouches[0].clientX || 0; - } - - /** - * Get the vertical mouse position from a mouse event - * @param {Event} event - * @return {Number} mouse y + * 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 */ - function getMouseY (event) { - if ('clientY' in event) return event.clientY; - return event.targetTouches[0] && event.targetTouches[0].clientY || 0; - } - - module.exports = Graph3d; - + DataSet.prototype.on = function(event, callback) { + var subscribers = this._subscribers[event]; + if (!subscribers) { + subscribers = []; + this._subscribers[event] = subscribers; + } -/***/ }, -/* 7 */ -/***/ function(module, exports, __webpack_require__) { + subscribers.push({ + callback: callback + }); + }; - var Point3d = __webpack_require__(10); + // TODO: make this function deprecated (replaced with `on` since version 0.5) + DataSet.prototype.subscribe = DataSet.prototype.on; /** - * @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 + * Unsubscribe from an event, remove an event listener + * @param {String} event + * @param {function} callback */ - function Camera() { - 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); + DataSet.prototype.off = function(event, callback) { + var subscribers = this._subscribers[event]; + if (subscribers) { + this._subscribers[event] = subscribers.filter(function (listener) { + return (listener.callback != callback); + }); + } + }; - this.calculateCameraOrientation(); - } + // TODO: make this function deprecated (replaced with `on` since version 0.5) + DataSet.prototype.unsubscribe = DataSet.prototype.off; /** - * 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 + * Trigger an event + * @param {String} event + * @param {Object | null} params + * @param {String} [senderId] Optional id of the sender. + * @private */ - Camera.prototype.setArmLocation = function(x, y, z) { - this.armLocation.x = x; - this.armLocation.y = y; - this.armLocation.z = z; + DataSet.prototype._trigger = function (event, params, senderId) { + if (event == '*') { + throw new Error('Cannot trigger event *'); + } - this.calculateCameraOrientation(); + var subscribers = []; + if (event in this._subscribers) { + subscribers = subscribers.concat(this._subscribers[event]); + } + if ('*' in this._subscribers) { + subscribers = subscribers.concat(this._subscribers['*']); + } + + for (var i = 0; i < subscribers.length; i++) { + var subscriber = subscribers[i]; + if (subscriber.callback) { + subscriber.callback(event, params, senderId || null); + } + } }; /** - * 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. + * 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 */ - Camera.prototype.setArmRotation = function(horizontal, vertical) { - if (horizontal !== undefined) { - this.armRotation.horizontal = horizontal; - } + DataSet.prototype.add = function (data, senderId) { + var addedIds = [], + id, + me = this; - 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 (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); + } - if (horizontal !== undefined || vertical !== undefined) { - this.calculateCameraOrientation(); + id = me._addItem(item); + addedIds.push(id); + } + } + else if (data instanceof Object) { + // Single item + id = me._addItem(data); + addedIds.push(id); + } + else { + throw new Error('Unknown dataType'); } - }; - /** - * Retrieve the current arm rotation - * @return {object} An object with parameters horizontal and vertical - */ - Camera.prototype.getArmRotation = function() { - var rot = {}; - rot.horizontal = this.armRotation.horizontal; - rot.vertical = this.armRotation.vertical; + if (addedIds.length) { + this._trigger('add', {items: addedIds}, senderId); + } - return rot; + return addedIds; }; /** - * Set the (normalized) length of the camera arm. - * @param {Number} length A length between 0.71 and 5.0 + * 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 */ - Camera.prototype.setArmLength = function(length) { - if (length === undefined) - return; - - this.armLength = length; + DataSet.prototype.update = function (data, senderId) { + var addedIds = []; + var updatedIds = []; + var updatedData = []; + var me = this; + var fieldId = me._fieldId; - // 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; + var addOrUpdate = function (item) { + var id = item[fieldId]; + if (me._data[id]) { + // update item + id = me._updateItem(item); + updatedIds.push(id); + updatedData.push(item); + } + else { + // add new item + id = me._addItem(item); + addedIds.push(id); + } + }; - this.calculateCameraOrientation(); - }; + 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); + } - /** - * Retrieve the arm length - * @return {Number} length - */ - Camera.prototype.getArmLength = function() { - return this.armLength; - }; + addOrUpdate(item); + } + } + else if (data instanceof Object) { + // Single item + addOrUpdate(data); + } + else { + throw new Error('Unknown dataType'); + } - /** - * Retrieve the camera location - * @return {Point3d} cameraLocation - */ - Camera.prototype.getCameraLocation = function() { - return this.cameraLocation; - }; + if (addedIds.length) { + this._trigger('add', {items: addedIds}, senderId); + } + if (updatedIds.length) { + this._trigger('update', {items: updatedIds, data: updatedData}, senderId); + } - /** - * Retrieve the camera rotation - * @return {Point3d} cameraRotation - */ - Camera.prototype.getCameraRotation = function() { - return this.cameraRotation; + return addedIds.concat(updatedIds); }; /** - * 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); - - // 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 = Camera; - -/***/ }, -/* 8 */ -/***/ function(module, exports, __webpack_require__) { - - var DataView = __webpack_require__(4); - - /** - * @class Filter + * Get a data item or multiple items. * - * @param {DataSet} data The google data table - * @param {Number} column The index of the column to be filtered - * @param {Graph} graph The graph + * 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 */ - function Filter (data, column, graph) { - this.data = data; - this.column = column; - this.graph = graph; // the parent graph + DataSet.prototype.get = function (args) { + var me = this; - this.index = undefined; - this.value = undefined; + // 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]; + } - // read all distinct values and select the first one - this.values = graph.getDistinctValues(data.get(), this.column); + // determine the return type + var returnType; + if (options && options.returnType) { + var allowedValues = ["DataTable", "Array", "Object"]; + returnType = allowedValues.indexOf(options.returnType) == -1 ? "Array" : options.returnType; - // sort both numeric and string values correctly - this.values.sort(function (a, b) { - return a > b ? 1 : a < b ? -1 : 0; - }); + if (data && (returnType != util.getType(data))) { + throw new Error('Type of parameter "data" (' + util.getType(data) + ') ' + + 'does not correspond with specified options.type (' + options.type + ')'); + } + if (returnType == 'DataTable' && !util.isDataTable(data)) { + throw new Error('Parameter "data" must be a DataTable ' + + 'when options.type is "DataTable"'); + } + } + else if (data) { + returnType = (util.getType(data) == 'DataTable') ? 'DataTable' : 'Array'; + } + else { + returnType = 'Array'; + } - if (this.values.length > 0) { - this.selectValue(0); + // build options + var type = options && options.type || this._options.type; + var filter = options && options.filter; + var items = [], item, itemId, i, len; + + // 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); + } + } + } } - // create an array with the filtered datapoints. this will be loaded afterwards - this.dataPoints = []; + // order the results + if (options && options.order && id == undefined) { + this._sort(items, options.order); + } - this.loaded = false; - this.onLoadCallback = undefined; + // 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); + } + } + } - if (graph.animationPreload) { - this.loaded = false; - this.loadInBackground(); + // 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 { - this.loaded = true; + // 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 data; + } + else { + // just return our array + return items; + } + } } }; - /** - * Return the label - * @return {string} label + * 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 */ - Filter.prototype.isLoaded = function() { - return this.loaded; - }; + 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 (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); + } + } + } - /** - * Return the loaded progress - * @return {Number} percentage between 0 and 100 - */ - Filter.prototype.getLoadedProgress = function() { - var len = this.values.length; + this._sort(items, order); - var i = 0; - while (this.dataPoints[i]) { - i++; + 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]); + } + } + } + } } + else { + // get all items + if (order) { + // create an ordered list + items = []; + for (id in data) { + if (data.hasOwnProperty(id)) { + items.push(data[id]); + } + } - return Math.round(i / len * 100); - }; + this._sort(items, order); + 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]); + } + } + } + } - /** - * Return the label - * @return {string} label - */ - Filter.prototype.getLabel = function() { - return this.graph.filterLabel; + return ids; }; - /** - * Return the columnIndex of the filter - * @return {Number} columnIndex + * Returns the DataSet itself. Is overwritten for example by the DataView, + * which returns the DataSet it is connected to instead. */ - Filter.prototype.getColumn = function() { - return this.column; + DataSet.prototype.getDataSet = function () { + return this; }; /** - * Return the currently selected value. Returns undefined if there is no selection - * @return {*} value + * 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. */ - Filter.prototype.getSelectedValue = function() { - if (this.index === undefined) - return undefined; + DataSet.prototype.forEach = function (callback, options) { + var filter = options && options.filter, + type = options && options.type || this._options.type, + data = this._data, + item, + id; - return this.values[this.index]; - }; + if (options && options.order) { + // execute forEach on ordered list + var items = this.get(options); - /** - * Retrieve all values of the filter - * @return {Array} values - */ - Filter.prototype.getValues = function() { - return this.values; + 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); + } + } + } + } }; /** - * Retrieve one value of the filter - * @param {Number} index - * @return {*} value + * 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 */ - Filter.prototype.getValue = function(index) { - if (index >= this.values.length) - throw 'Error: index out of range'; + DataSet.prototype.map = function (callback, options) { + var filter = options && options.filter, + type = options && options.type || this._options.type, + mappedItems = [], + data = this._data, + item; - return this.values[index]; - }; + // 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)); + } + } + } + + // order items + if (options && options.order) { + this._sort(mappedItems, options.order); + } + return mappedItems; + }; /** - * Retrieve the (filtered) dataPoints for the currently selected filter index - * @param {Number} [index] (optional) - * @return {Array} dataPoints + * Filter the fields of an item + * @param {Object | null} item + * @param {String[]} fields Field names + * @return {Object | null} filteredItem or null if no item is provided + * @private */ - 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]; + DataSet.prototype._filterFields = function (item, fields) { + if (!item) { // item is null + return item; } - 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); + var filteredItem = {}; - this.dataPoints[index] = dataPoints; + for (var field in item) { + if (item.hasOwnProperty(field) && (fields.indexOf(field) != -1)) { + filteredItem[field] = item[field]; + } } - return dataPoints; + return filteredItem; }; - - /** - * Set a callback function when the filter is fully loaded. + * Sort the provided array with items + * @param {Object[]} items + * @param {String | function} order A field name or custom sort function. + * @private */ - Filter.prototype.setOnLoadCallback = function(callback) { - this.onLoadCallback = callback; + 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'); + } }; - /** - * Add a value to the list with available values for this filter - * No double entries will be created. - * @param {Number} index + * 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 */ - Filter.prototype.selectValue = function(index) { - if (index >= this.values.length) - throw 'Error: index out of range'; + DataSet.prototype.remove = function (id, senderId) { + var removedIds = [], + i, len, removedId; - this.index = index; - this.value = this.values[index]; + 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); + } + } + + if (removedIds.length) { + this._trigger('remove', {items: removedIds}, senderId); + } + + return removedIds; }; /** - * Load all filtered rows in the background one by one - * Start this method without providing an index! + * Remove an item by its id + * @param {Number | String | Object} id id or item + * @returns {Number | String | null} id + * @private */ - 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); + DataSet.prototype._remove = function (id) { + if (util.isNumber(id) || util.isString(id)) { + if (this._data[id]) { + delete this._data[id]; + this.length--; + return id; } - var progress = this.getLoadedProgress(); - frame.progress.innerHTML = 'Loading animation... ' + progress + '%'; - // TODO: this is no nice solution... - frame.progress.style.bottom = 60 + 'px'; // TODO: use height of slider - frame.progress.style.left = 10 + 'px'; - - var me = this; - setTimeout(function() {me.loadInBackground(index+1);}, 10); - this.loaded = false; } - else { - this.loaded = true; - - // remove the progress box - if (frame.progress !== undefined) { - frame.removeChild(frame.progress); - frame.progress = undefined; + else if (id instanceof Object) { + var itemId = id[this._fieldId]; + if (itemId && this._data[itemId]) { + delete this._data[itemId]; + this.length--; + return itemId; } - - if (this.onLoadCallback) - this.onLoadCallback(); } + return null; }; - module.exports = Filter; - - -/***/ }, -/* 9 */ -/***/ function(module, exports, __webpack_require__) { - /** - * @prototype Point2d - * @param {Number} [x] - * @param {Number} [y] + * Clear the data + * @param {String} [senderId] Optional sender id + * @return {Array} removedIds The ids of all removed items */ - function Point2d (x, y) { - this.x = x !== undefined ? x : 0; - this.y = y !== undefined ? y : 0; - } - - module.exports = Point2d; + DataSet.prototype.clear = function (senderId) { + var ids = Object.keys(this._data); + this._data = {}; + this.length = 0; -/***/ }, -/* 10 */ -/***/ function(module, exports, __webpack_require__) { + this._trigger('remove', {items: ids}, senderId); - /** - * @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; + return ids; }; /** - * Subtract the two provided points, returns a-b - * @param {Point3d} a - * @param {Point3d} b - * @return {Point3d} a-b + * 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 */ - 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; - }; + DataSet.prototype.max = function (field) { + var data = this._data, + max = null, + maxField = null; - /** - * 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; - }; + 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; + } + } + } - /** - * 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 - ); + return max; }; /** - * 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 + * 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 */ - Point3d.crossProduct = function(a, b) { - var crossproduct = new Point3d(); + DataSet.prototype.min = function (field) { + var data = this._data, + min = null, + minField = null; - 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; + 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; + } + } + } - return crossproduct; + return min; }; - /** - * Rtrieve the length of the vector (or the distance from this point to the origin - * @return {Number} length + * 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. */ - Point3d.prototype.length = function() { - return Math.sqrt( - this.x * this.x + - this.y * this.y + - this.z * this.z - ); - }; - - module.exports = Point3d; + 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; + 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++; + } + } + } -/***/ }, -/* 11 */ -/***/ function(module, exports, __webpack_require__) { + if (fieldType) { + for (i = 0; i < values.length; i++) { + values[i] = util.convert(values[i], fieldType); + } + } - var util = __webpack_require__(1); + return values; + }; /** - * @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. + * Add a single item. Will fail when an item with the same id already exists. + * @param {Object} item + * @return {String} id + * @private */ - 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); + DataSet.prototype._addItem = function (item) { + var id = item[this._fieldId]; - // create events - var me = this; - this.frame.slide.onmousedown = function (event) {me._onMouseDown(event);}; - this.frame.prev.onclick = function (event) {me.prev(event);}; - this.frame.play.onclick = function (event) {me.togglePlay(event);}; - this.frame.next.onclick = function (event) {me.next(event);}; + if (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; } - this.onChangeCallback = undefined; - - this.values = []; - this.index = undefined; + var d = {}; + for (var field in item) { + if (item.hasOwnProperty(field)) { + var fieldType = this._type[field]; // type may be undefined + d[field] = util.convert(item[field], fieldType); + } + } + this._data[id] = d; + this.length++; - this.playTimeout = undefined; - this.playInterval = 1000; // milliseconds - this.playLoop = true; - } + return id; + }; /** - * Select the previous index + * 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 */ - Slider.prototype.prev = function() { - var index = this.getIndex(); - if (index > 0) { - index--; - this.setIndex(index); + DataSet.prototype._getItem = function (id, types) { + var field, value; + + // get the item from the dataset + var raw = this._data[id]; + if (!raw) { + return null; } - }; - /** - * Select the next index - */ - Slider.prototype.next = function() { - var index = this.getIndex(); - if (index < this.values.length - 1) { - index++; - this.setIndex(index); + // 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; }; /** - * Select the next index + * 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 */ - Slider.prototype.playNext = function() { - var start = new Date(); - - var index = this.getIndex(); - if (index < this.values.length - 1) { - index++; - this.setIndex(index); + 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) + ')'); } - else if (this.playLoop) { - // jump to the start - index = 0; - this.setIndex(index); + var d = this._data[id]; + if (!d) { + // item doesn't exist + throw new Error('Cannot update item: no item with id ' + id + ' found'); } - 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 + // 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); + } + } - var me = this; - this.playTimeout = setTimeout(function() {me.playNext();}, interval); + return id; }; /** - * Toggle start or stop playing + * Get an array with the column names of a Google DataTable + * @param {DataTable} dataTable + * @return {String[]} columnNames + * @private */ - Slider.prototype.togglePlay = function() { - if (this.playTimeout === undefined) { - this.play(); - } else { - this.stop(); + 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; }; /** - * Start playing + * Append an item as a row to the dataTable + * @param dataTable + * @param columns + * @param item + * @private */ - Slider.prototype.play = function() { - // Test whether already playing - if (this.playTimeout) return; - - this.playNext(); + DataSet.prototype._appendRow = function (dataTable, columns, item) { + var row = dataTable.addRow(); - if (this.frame) { - this.frame.play.value = 'Stop'; + for (var col = 0, cols = columns.length; col < cols; col++) { + var field = columns[col]; + dataTable.setValue(row, col, item[field]); } }; - /** - * Stop playing - */ - Slider.prototype.stop = function() { - clearInterval(this.playTimeout); - this.playTimeout = undefined; - - if (this.frame) { - this.frame.play.value = 'Play'; - } - }; + module.exports = DataSet; - /** - * Set a callback function which will be triggered when the value of the - * slider bar has changed. - */ - Slider.prototype.setOnChangeCallback = function(callback) { - this.onChangeCallback = callback; - }; - /** - * Set the interval for playing the list - * @param {Number} interval The interval in milliseconds - */ - Slider.prototype.setPlayInterval = function(interval) { - this.playInterval = interval; - }; +/***/ }, +/* 8 */ +/***/ function(module, exports, __webpack_require__) { /** - * Retrieve the current play interval - * @return {Number} interval The interval in milliseconds + * A queue + * @param {Object} options + * Available options: + * - delay: number When provided, the queue will be flushed + * automatically after an inactivity of this delay + * in milliseconds. + * Default value is null. + * - max: number When the queue exceeds the given maximum number + * of entries, the queue is flushed automatically. + * Default value of max is Infinity. + * @constructor */ - Slider.prototype.getPlayInterval = function(interval) { - return this.playInterval; - }; + function Queue(options) { + // options + this.delay = null; + this.max = Infinity; - /** - * 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. - */ - Slider.prototype.setPlayLoop = function(doLoop) { - this.playLoop = doLoop; - }; + // properties + this._queue = []; + this._timeout = null; + this._extended = null; + this.setOptions(options); + } /** - * Execute the onchange callback function + * Update the configuration of the queue + * @param {Object} options + * Available options: + * - delay: number When provided, the queue will be flushed + * automatically after an inactivity of this delay + * in milliseconds. + * Default value is null. + * - max: number When the queue exceeds the given maximum number + * of entries, the queue is flushed automatically. + * Default value of max is Infinity. + * @param options */ - Slider.prototype.onChange = function() { - if (this.onChangeCallback !== undefined) { - this.onChangeCallback(); + Queue.prototype.setOptions = function (options) { + if (options && typeof options.delay !== 'undefined') { + this.delay = options.delay; + } + if (options && typeof options.max !== 'undefined') { + this.max = options.max; } + + this._flushIfNeeded(); }; /** - * redraw the slider on the correct place - */ - 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'; + * Extend an object with queuing functionality. + * The object will be extended with a function flush, and the methods provided + * in options.replace will be replaced with queued ones. + * @param {Object} object + * @param {Object} options + * Available options: + * - replace: Array. + * A list with method names of the methods + * on the object to be replaced with queued ones. + * - delay: number When provided, the queue will be flushed + * automatically after an inactivity of this delay + * in milliseconds. + * Default value is null. + * - max: number When the queue exceeds the given maximum number + * of entries, the queue is flushed automatically. + * Default value of max is Infinity. + * @return {Queue} Returns the created queue + */ + Queue.extend = function (object, options) { + var queue = new Queue(options); - // position the slider button - var left = this.indexToLeft(this.index); - this.frame.slide.style.left = (left) + 'px'; + if (object.flush !== undefined) { + throw new Error('Target object already has a property flush'); } - }; + object.flush = function () { + queue.flush(); + }; + + var methods = [{ + name: 'flush', + original: undefined + }]; + + if (options && options.replace) { + for (var i = 0; i < options.replace.length; i++) { + var name = options.replace[i]; + methods.push({ + name: name, + original: object[name] + }); + queue.replace(object, name); + } + } + + queue._extended = { + object: object, + methods: methods + }; + return queue; + }; /** - * Set the list with values for the slider - * @param {Array} values A javascript array with values (any type) + * Destroy the queue. The queue will first flush all queued actions, and in + * case it has extended an object, will restore the original object. */ - Slider.prototype.setValues = function(values) { - this.values = values; + Queue.prototype.destroy = function () { + this.flush(); - if (this.values.length > 0) - this.setIndex(0); - else - this.index = undefined; + if (this._extended) { + var object = this._extended.object; + var methods = this._extended.methods; + for (var i = 0; i < methods.length; i++) { + var method = methods[i]; + if (method.original) { + object[method.name] = method.original; + } + else { + delete object[method.name]; + } + } + this._extended = null; + } }; /** - * Select a value by its index - * @param {Number} index + * Replace a method on an object with a queued version + * @param {Object} object Object having the method + * @param {string} method The method name */ - Slider.prototype.setIndex = function(index) { - if (index < this.values.length) { - this.index = index; + Queue.prototype.replace = function(object, method) { + var me = this; + var original = object[method]; + if (!original) { + throw new Error('Method ' + method + ' undefined'); + } - this.redraw(); - this.onChange(); + object[method] = function () { + // create an Array with the arguments + var args = []; + for (var i = 0; i < arguments.length; i++) { + args[i] = arguments[i]; + } + + // add this call to the queue + me.queue({ + args: args, + fn: original, + context: this + }); + }; + }; + + /** + * Queue a call + * @param {function | {fn: function, args: Array} | {fn: function, args: Array, context: Object}} entry + */ + Queue.prototype.queue = function(entry) { + if (typeof entry === 'function') { + this._queue.push({fn: entry}); } else { - throw 'Error: index out of range'; + this._queue.push(entry); } + + this._flushIfNeeded(); }; /** - * retrieve the index of the currently selected vaue - * @return {Number} index + * Check whether the queue needs to be flushed + * @private */ - Slider.prototype.getIndex = function() { - return this.index; - }; + Queue.prototype._flushIfNeeded = function () { + // flush when the maximum is exceeded. + if (this._queue.length > this.max) { + this.flush(); + } + // flush after a period of inactivity when a delay is configured + clearTimeout(this._timeout); + if (this.queue.length > 0 && typeof this.delay === 'number') { + var me = this; + this._timeout = setTimeout(function () { + me.flush(); + }, this.delay); + } + }; /** - * retrieve the currently selected value - * @return {*} value + * Flush all queued calls */ - Slider.prototype.get = function() { - return this.values[this.index]; + Queue.prototype.flush = function () { + while (this._queue.length > 0) { + var entry = this._queue.shift(); + entry.fn.apply(entry.context || entry.fn, entry.args || []); + } }; + module.exports = Queue; - 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); - - 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', this.onmousemove); - util.addEventListener(document, 'mouseup', this.onmouseup); - util.preventDefault(event); - }; +/***/ }, +/* 9 */ +/***/ function(module, exports, __webpack_require__) { - Slider.prototype.leftToIndex = function (left) { - var width = parseFloat(this.frame.bar.style.width) - - this.frame.slide.clientWidth - 10; - var x = left - 3; + var util = __webpack_require__(1); + var DataSet = __webpack_require__(7); - 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; + /** + * 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.length = 0; // number of items in the DataView + this._options = options || {}; + this._fieldId = 'id'; // name of the field containing id + this._subscribers = {}; // event subscribers - return index; - }; + var me = this; + this.listener = function () { + me._onEvent.apply(me, arguments); + }; - Slider.prototype.indexToLeft = function (index) { - var width = parseFloat(this.frame.bar.style.width) - - this.frame.slide.clientWidth - 10; + this.setData(data); + } - var x = index / (this.values.length-1) * width; - var left = x + 3; + // TODO: implement a function .config() to dynamically update things like configured filter + // and trigger changes accordingly - return left; - }; + /** + * 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); + } + // 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.length = 0; + this._trigger('remove', {items: ids}); + } - Slider.prototype._onMouseMove = function (event) { - var diff = event.clientX - this.startClientX; - var x = this.startSlideX + diff; + this._data = data; - var index = this.leftToIndex(x); + if (this._data) { + // update fieldId + this._fieldId = this._options.fieldId || + (this._data && this._data.options && this._data.options.fieldId) || + 'id'; - this.setIndex(index); + // 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.length = ids.length; + this._trigger('add', {items: ids}); - util.preventDefault(); + // subscribe to new dataset + if (this._data.on) { + this._data.on('*', this.listener); + } + } }; + /** + * Refresh the DataView. Useful when the DataView has a filter function + * containing a variable parameter. + */ + DataView.prototype.refresh = function () { + var id; + var ids = this._data.getIds({filter: this._options && this._options.filter}); + var newIds = {}; + var added = []; + var removed = []; - Slider.prototype._onMouseUp = function (event) { - this.frame.style.cursor = 'auto'; + // check for additions + for (var i = 0; i < ids.length; i++) { + id = ids[i]; + newIds[id] = true; + if (!this._ids[id]) { + added.push(id); + this._ids[id] = true; + this.length++; + } + } - // remove event listeners - util.removeEventListener(document, 'mousemove', this.onmousemove); - util.removeEventListener(document, 'mouseup', this.onmouseup); + // check for removals + for (id in this._ids) { + if (this._ids.hasOwnProperty(id)) { + if (!newIds[id]) { + removed.push(id); + delete this._ids[id]; + this.length--; + } + } + } - util.preventDefault(); + // trigger events + if (added.length) { + this._trigger('add', {items: added}); + } + if (removed.length) { + this._trigger('remove', {items: removed}); + } }; - module.exports = Slider; - - -/***/ }, -/* 12 */ -/***/ function(module, exports, __webpack_require__) { - /** - * @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. + * Get data from the data view * - * 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, .... + * Usage: * - * Example usage: - * var step = new StepNumber(0, 10, 2.5, true); - * step.start(); - * while (!step.end()) { - * alert(step.getCurrent()); - * step.next(); - * } + * get() + * get(options: Object) + * get(options: Object, data: Array | DataTable) * - * Version: 1.0 + * get(id: Number) + * get(id: Number, options: Object) + * get(id: Number, options: Object, data: Array | DataTable) * - * @param {Number} start The start value - * @param {Number} end The end value - * @param {Number} step Optional. Step size. Must be a positive value. - * @param {boolean} prettyStep Optional. If true, the step size is rounded - * To a pretty step size (like 1, 2, 5, 10, 20, 50, ...) - */ - function StepNumber(start, end, step, prettyStep) { - // set default values - this._start = 0; - this._end = 0; - this._step = 1; - this.prettyStep = true; - this.precision = 5; - - this._current = 0; - this.setRange(start, end, step, prettyStep); - }; - - /** - * Set a new range: start, end and step. + * get(ids: Number[]) + * get(ids: Number[], options: Object) + * get(ids: Number[], options: Object, data: Array | DataTable) * - * @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, ...) + * 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 */ - StepNumber.prototype.setRange = function(start, end, step, prettyStep) { - this._start = start ? start : 0; - this._end = end ? end : 0; + DataView.prototype.get = function (args) { + var me = this; - this.setStep(step, prettyStep); - }; + // 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]; + } - /** - * 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; + // extend the options with the default options and provided options + var viewOptions = util.extend({}, this._options, options); - if (prettyStep !== undefined) - this.prettyStep = prettyStep; + // 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); + } + } - if (this.prettyStep === true) - this._step = StepNumber.calculatePrettyStep(step); - else - this._step = step; + // build up the call to the linked data set + var getArguments = []; + if (ids != undefined) { + getArguments.push(ids); + } + getArguments.push(viewOptions); + getArguments.push(data); + + return this._data && this._data.get.apply(this._data, getArguments); }; /** - * 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 + * 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 */ - StepNumber.calculatePrettyStep = function (step) { - var log10 = function (x) {return Math.log(x) / Math.LN10;}; + DataView.prototype.getIds = function (options) { + var ids; - // 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))); + if (this._data) { + var defaultFilter = this._options.filter; + var filter; - // 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 (options && options.filter) { + if (defaultFilter) { + filter = function (item) { + return defaultFilter(item) && options.filter(item); + } + } + else { + filter = options.filter; + } + } + else { + filter = defaultFilter; + } - // for safety - if (prettyStep <= 0) { - prettyStep = 1; + ids = this._data.getIds({ + filter: filter, + order: options && options.order + }); + } + else { + ids = []; } - return prettyStep; + return ids; }; /** - * returns the current value of the step - * @return {Number} current value + * 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 */ - StepNumber.prototype.getCurrent = function () { - return parseFloat(this._current.toPrecision(this.precision)); + DataView.prototype.getDataSet = function () { + var dataSet = this; + while (dataSet instanceof DataView) { + dataSet = dataSet._data; + } + return dataSet || null; }; /** - * returns the current step size - * @return {Number} current step size - */ - StepNumber.prototype.getStep = function () { - return this._step; - }; - - /** - * Set the current value to the largest value smaller than start, which - * is a multiple of the step size + * 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 */ - StepNumber.prototype.start = function() { - this._current = this._start - this._start % this._step; - }; + DataView.prototype._onEvent = function (event, params, senderId) { + var i, len, id, item, + ids = params && params.items, + data = this._data, + added = [], + updated = [], + removed = []; - /** - * Do a step, add the step size to the current value - */ - StepNumber.prototype.next = function () { - this._current += this._step; - }; + 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); + } + } - /** - * 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); + 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; + } + + this.length += added.length - removed.length; + + 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); + } + } }; - module.exports = StepNumber; + // copy subscription functionality from DataSet + DataView.prototype.on = DataSet.prototype.on; + DataView.prototype.off = DataSet.prototype.off; + DataView.prototype._trigger = DataSet.prototype._trigger; + + // TODO: make these functions deprecated (replaced with `on` and `off` since version 0.5) + DataView.prototype.subscribe = DataView.prototype.on; + DataView.prototype.unsubscribe = DataView.prototype.off; + module.exports = DataView; /***/ }, -/* 13 */ +/* 10 */ /***/ function(module, exports, __webpack_require__) { - var Emitter = __webpack_require__(56); - var Hammer = __webpack_require__(45); + var Emitter = __webpack_require__(11); + var DataSet = __webpack_require__(7); + var DataView = __webpack_require__(9); var util = __webpack_require__(1); - var DataSet = __webpack_require__(3); - var DataView = __webpack_require__(4); - var Range = __webpack_require__(17); - var Core = __webpack_require__(46); - var TimeAxis = __webpack_require__(30); - var CurrentTime = __webpack_require__(21); - var CustomTime = __webpack_require__(22); - var ItemSet = __webpack_require__(27); + var Point3d = __webpack_require__(12); + var Point2d = __webpack_require__(13); + var Camera = __webpack_require__(14); + var Filter = __webpack_require__(15); + var Slider = __webpack_require__(16); + var StepNumber = __webpack_require__(17); /** - * Create a timeline visualization - * @param {HTMLElement} container - * @param {vis.DataSet | vis.DataView | Array | google.visualization.DataTable} [items] - * @param {vis.DataSet | vis.DataView | Array | google.visualization.DataTable} [groups] - * @param {Object} [options] See Timeline.setOptions for the available options. - * @constructor - * @extends Core + * @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 Timeline (container, items, groups, options) { - if (!(this instanceof Timeline)) { + function Graph3d(container, data, options) { + if (!(this instanceof Graph3d)) { throw new SyntaxError('Constructor must be called with the new operator'); } - // if the third element is options, the forth is groups (optionally); - if (!(Array.isArray(groups) || groups instanceof DataSet || groups instanceof DataView) && groups instanceof Object) { - var forthArgument = options; - options = groups; - groups = forthArgument; - } + // 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%'; - var me = this; - this.defaultOptions = { - start: null, - end: null, + this.xLabel = 'x'; + this.yLabel = 'y'; + this.zLabel = 'z'; - autoResize: true, + var passValueFn = function(v) { return v; }; + this.xValueLabel = passValueFn; + this.yValueLabel = passValueFn; + this.zValueLabel = passValueFn; + + this.filterLabel = 'time'; + this.legendLabel = 'value'; - orientation: 'bottom', - width: null, - height: null, - maxHeight: null, - minHeight: null - }; - this.options = util.deepExtend({}, this.defaultOptions); + 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' - // Create the DOM, props, and emitter - this._create(container); + this.animationInterval = 1000; // milliseconds + this.animationPreload = false; - // all components listed here will be repainted automatically - this.components = []; + this.camera = new Camera(); + this.eye = new Point3d(0, 0, -1); // TODO: set eye.z about 3/4 of the width of the window? - this.body = { - dom: this.dom, - domProps: this.props, - emitter: { - on: this.on.bind(this), - off: this.off.bind(this), - emit: this.emit.bind(this) - }, - hiddenDates: [], - util: { - getScale: function () { - return me.timeAxis.step.scale; - }, - getStep: function () { - return me.timeAxis.step.step; - }, + this.dataTable = null; // The original data table + this.dataPoints = null; // The table with point objects - 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) - } - }; + // the column indexes + this.colX = undefined; + this.colY = undefined; + this.colZ = undefined; + this.colValue = undefined; + this.colFilter = undefined; - // range - this.range = new Range(this.body); - this.components.push(this.range); - this.body.range = this.range; + 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 - // time axis - this.timeAxis = new TimeAxis(this.body); - this.components.push(this.timeAxis); + // constants + this.colorAxis = '#4D4D4D'; + this.colorGrid = '#D3D3D3'; + this.colorDot = '#7DC1FF'; + this.colorDotBorder = '#3267D2'; - // current time bar - this.currentTime = new CurrentTime(this.body); - this.components.push(this.currentTime); + // create a frame and canvas + this.create(); - // 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); + // apply options (also when undefined) + this.setOptions(options); - // item set - this.itemSet = new ItemSet(this.body); - this.components.push(this.itemSet); + // apply data + if (data) { + this.setData(data); + } + } - this.itemsData = null; // DataSet - this.groupsData = null; // DataSet + // Extend Graph3d with an Emitter mixin + Emitter(Graph3d.prototype); - // apply options - if (options) { - this.setOptions(options); - } + /** + * 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)); - // IMPORTANT: THIS HAPPENS BEFORE SET ITEMS! - if (groups) { - this.setGroups(groups); + // 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; + } } - // create itemset - if (items) { - this.setItems(items); - } - else { - this._redraw(); - } - } + // scale the vertical axis + this.scale.z *= this.verticalRatio; + // TODO: can this be automated? verticalRatio? + + // 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); + }; - // Extend the functionality from Core - Timeline.prototype = new Core(); /** - * Force a redraw. The size of all items will be recalculated. - * Can be useful to manually redraw when option autoResize=false and the window - * has been resized, or when the items CSS has been changed. + * 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 */ - Timeline.prototype.redraw = function() { - this.itemSet && this.itemSet.markDirty({refreshItems: true}); - this._redraw(); + Graph3d.prototype._convert3Dto2D = function(point3d) { + var translation = this._convertPointToTranslation(point3d); + return this._convertTranslationToScreen(translation); }; /** - * Set items - * @param {vis.DataSet | Array | google.visualization.DataTable | null} items + * 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 */ - 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' - } - }); - } + Graph3d.prototype._convertPointToTranslation = function(point3d) { + var ax = point3d.x * this.scale.x, + ay = point3d.y * this.scale.y, + az = point3d.z * this.scale.z, - // set items - this.itemsData = newDataSet; - this.itemSet && this.itemSet.setItems(newDataSet); + cx = this.camera.getCameraLocation().x, + cy = this.camera.getCameraLocation().y, + cz = this.camera.getCameraLocation().z, - if (initialLoad) { - if (this.options.start != undefined || this.options.end != undefined) { - if (this.options.start == undefined || this.options.end == undefined) { - var dataRange = this._getDataRange(); - } + // 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), - var start = this.options.start != undefined ? this.options.start : dataRange.start; - var end = this.options.end != undefined ? this.options.end : dataRange.end; + // 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)); - this.setWindow(start, end, {animate: false}); - } - else { - this.fit({animate: false}); - } - } + return new Point3d(dx, dy, dz); }; /** - * Set groups - * @param {vis.DataSet | Array | google.visualization.DataTable} groups + * 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 */ - 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; + Graph3d.prototype._convertTranslationToScreen = function(translation) { + var ex = this.eye.x, + ey = this.eye.y, + ez = this.eye.z, + dx = translation.x, + dy = translation.y, + dz = translation.z; + + // calculate position on screen from translation + var bx; + var by; + if (this.showPerspective) { + bx = (dx - ex) * (ez / dz); + by = (dy - ey) * (ez / dz); } else { - // turn an array into a dataset - newDataSet = new DataSet(groups); + bx = dx * -(ez / this.camera.getArmLength()); + by = dy * -(ez / this.camera.getArmLength()); } - this.groupsData = newDataSet; - this.itemSet.setGroups(newDataSet); + // 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); }; /** - * Set selected items by their id. Replaces the current selection - * Unknown id's are silently ignored. - * @param {string[] | string} [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. - * @param {Object} [options] Available options: - * `focus: boolean` - * If true, focus will be set to the selected item(s) - * `animate: boolean | number` - * If true (default), the range is animated - * smoothly to the new window. - * If a number, the number is taken as duration - * for the animation. Default duration is 500 ms. - * Only applicable when option focus is true. + * Set the background styling for the graph + * @param {string | {fill: string, stroke: string, strokeWidth: string}} backgroundColor */ - Timeline.prototype.setSelection = function(ids, options) { - this.itemSet && this.itemSet.setSelection(ids); + Graph3d.prototype._setBackgroundColor = function(backgroundColor) { + var fill = 'white'; + var stroke = 'gray'; + var strokeWidth = 1; - if (options && options.focus) { - this.focus(ids, options); + 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'; + }; + + + /// 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 }; /** - * Get the selected items by their id - * @return {Array} ids The ids of the selected items + * 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 */ - Timeline.prototype.getSelection = function() { - return this.itemSet && this.itemSet.getSelection() || []; + 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 -1; }; /** - * Adjust the visible window such that the selected item (or multiple items) - * are centered on screen. - * @param {String | String[]} id An item id or array with item ids - * @param {Object} [options] Available options: - * `animate: boolean | number` - * If true (default), the range is animated - * smoothly to the new window. - * If a number, the number is taken as duration - * for the animation. Default duration is 500 ms. - * Only applicable when option focus is true + * Determine the indexes of the data columns, based on the given style and data + * @param {DataSet} data + * @param {Number} style */ - Timeline.prototype.focus = function(id, options) { - if (!this.itemsData || id == undefined) return; - - var ids = Array.isArray(id) ? id : [id]; - - // get the specified item(s) - var itemsData = this.itemsData.getDataSet().get(ids, { - type: { - start: 'Date', - end: 'Date' - } - }); - - // calculate minimum start and maximum end of specified items - var start = null; - var end = null; - itemsData.forEach(function (itemData) { - var s = itemData.start.valueOf(); - var e = 'end' in itemData ? itemData.end.valueOf() : itemData.start.valueOf(); + 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; - if (start === null || s < start) { - start = s; + 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; - if (end === null || e > end) { - end = e; + if (data.getNumberOfColumns() > 4) { + this.colFilter = 4; } - }); - - if (start !== null && end !== null) { - // calculate the new middle and interval for the window - var middle = (start + end) / 2; - var interval = Math.max((this.range.end - this.range.start), (end - start) * 1.1); - - var animate = (options && options.animate !== undefined) ? options.animate : true; - this.range.setRange(middle - interval / 2, middle + interval / 2, animate); + } + else { + throw 'Unknown style "' + this.style + '"'; } }; - /** - * Get the data range of the item set. - * @returns {{min: Date, max: Date}} range A range with a start and end Date. - * When no minimum is found, min==null - * When no maximum is found, max==null - */ - Timeline.prototype.getItemRange = function() { - // calculate min from start filed - var dataset = this.itemsData.getDataSet(), - min = null, - max = null; + Graph3d.prototype.getNumberOfRows = function(data) { + return data.length; + } - if (dataset) { - // calculate the minimum value of the field 'start' - var minItem = dataset.min('start'); - min = minItem ? util.convert(minItem.start, 'Date').valueOf() : null; - // Note: we convert first to Date and then to number because else - // a conversion from ISODate to Number will fail - // calculate 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()); - } + Graph3d.prototype.getNumberOfColumns = function(data) { + var counter = 0; + for (var column in data[0]) { + if (data[0].hasOwnProperty(column)) { + counter++; } } + return counter; + } - return { - min: (min != null) ? new Date(min) : null, - max: (max != null) ? new Date(max) : null - }; - }; - - - module.exports = Timeline; + 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; + } -/***/ }, -/* 14 */ -/***/ function(module, exports, __webpack_require__) { - var Emitter = __webpack_require__(56); - var Hammer = __webpack_require__(45); - var util = __webpack_require__(1); - var DataSet = __webpack_require__(3); - var DataView = __webpack_require__(4); - var Range = __webpack_require__(17); - var Core = __webpack_require__(46); - var TimeAxis = __webpack_require__(30); - var CurrentTime = __webpack_require__(21); - var CustomTime = __webpack_require__(22); - var LineGraph = __webpack_require__(29); + 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; + }; /** - * 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 - * @extends Core + * 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 */ - function Graph2d (container, items, groups, options) { - // if the third element is options, the forth is groups (optionally); - if (!(Array.isArray(groups) || groups instanceof DataSet) && groups instanceof Object) { - var forthArgument = options; - options = groups; - groups = forthArgument; - } - + Graph3d.prototype._dataInitialize = function (rawData, style) { var me = this; - this.defaultOptions = { - start: null, - end: null, - - autoResize: true, - - orientation: 'bottom', - width: null, - height: null, - maxHeight: null, - minHeight: null - }; - this.options = util.deepExtend({}, this.defaultOptions); - // Create the DOM, props, and emitter - this._create(container); + // unsubscribe from the dataTable + if (this.dataSet) { + this.dataSet.off('*', this._onChange); + } - // all components listed here will be repainted automatically - this.components = []; + if (rawData === undefined) + return; - this.body = { - dom: this.dom, - domProps: this.props, - emitter: { - on: this.on.bind(this), - off: this.off.bind(this), - emit: this.emit.bind(this) - }, - hiddenDates: [], - util: { - 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 (Array.isArray(rawData)) { + rawData = new DataSet(rawData); + } - // range - this.range = new Range(this.body); - this.components.push(this.range); - this.body.range = this.range; + var data; + if (rawData instanceof DataSet || rawData instanceof DataView) { + data = rawData.get(); + } + else { + throw new Error('Array, DataSet, or DataView expected'); + } - // time axis - this.timeAxis = new TimeAxis(this.body); - this.components.push(this.timeAxis); - //this.body.util.snap = this.timeAxis.snap.bind(this.timeAxis); + if (data.length == 0) + return; - // current time bar - this.currentTime = new CurrentTime(this.body); - this.components.push(this.currentTime); + this.dataSet = rawData; + this.dataTable = data; - // 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); + // subscribe to changes in the dataset + this._onChange = function () { + me.setData(me.dataSet); + }; + this.dataSet.on('*', this._onChange); - // item set - this.linegraph = new LineGraph(this.body); - this.components.push(this.linegraph); + // _determineColumnIndexes + // getNumberOfRows (points) + // getNumberOfColumns (x,y,z,v,t,t1,t2...) + // getDistinctValues (unique values?) + // getColumnRange - this.itemsData = null; // DataSet - this.groupsData = null; // DataSet + // 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'; - // apply options - if (options) { - this.setOptions(options); - } - // IMPORTANT: THIS HAPPENS BEFORE SET ITEMS! - if (groups) { - this.setGroups(groups); - } - // create itemset - if (items) { - this.setItems(items); - } - else { - this._redraw(); + // 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();}); + } } - } - - // Extend the functionality from Core - Graph2d.prototype = new Core(); - /** - * Set items - * @param {vis.DataSet | Array | google.visualization.DataTable | null} items - */ - Graph2d.prototype.setItems = function(items) { - var initialLoad = (this.itemsData == null); - - // convert to type DataSet when needed - var newDataSet; - if (!items) { - newDataSet = null; - } - else if (items instanceof DataSet || items instanceof DataView) { - newDataSet = items; - } - 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); + var withBars = this.style == Graph3d.STYLE.BAR || + this.style == Graph3d.STYLE.BARCOLOR || + this.style == Graph3d.STYLE.BARSIZE; - if (initialLoad) { - if (this.options.start != undefined || this.options.end != undefined) { - var start = this.options.start != undefined ? this.options.start : null; - var end = this.options.end != undefined ? this.options.end : null; + // 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.setWindow(start, end, {animate: false}); + if (this.defaultYBarWidth !== undefined) { + this.yBarWidth = this.defaultYBarWidth; } else { - this.fit({animate: false}); + var dataY = this.getDistinctValues(data,this.colY); + this.yBarWidth = (dataY[1] - dataY[0]) || 1; } } - }; - /** - * Set groups - * @param {vis.DataSet | Array | google.visualization.DataTable} groups - */ - Graph2d.prototype.setGroups = function(groups) { - // convert to type DataSet when needed - var newDataSet; - if (!groups) { - newDataSet = null; + // calculate minimums and maximums + var xRange = this.getColumnRange(data,this.colX); + if (withBars) { + xRange.min -= this.xBarWidth / 2; + xRange.max += this.xBarWidth / 2; } - else if (groups instanceof DataSet || groups instanceof DataView) { - newDataSet = groups; + 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; } - else { - // turn an array into a dataset - newDataSet = new DataSet(groups); + 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; + + if (this.colValue !== undefined) { + var valueRange = this.getColumnRange(data,this.colValue); + this.valueMin = (this.defaultValueMin !== undefined) ? this.defaultValueMin : valueRange.min; + this.valueMax = (this.defaultValueMax !== undefined) ? this.defaultValueMax : valueRange.max; + if (this.valueMax <= this.valueMin) this.valueMax = this.valueMin + 1; } - this.groupsData = newDataSet; - this.linegraph.setGroups(newDataSet); + // set the scale dependent on the ranges. + this._setScale(); }; - /** - * Returns an object containing an SVG element with the icon of the group (size determined by iconWidth and iconHeight), the label of the group (content) and the yAxisOrientation of the group (left or right). - * @param groupId - * @param width - * @param height - */ - Graph2d.prototype.getLegend = function(groupId, width, height) { - if (width === undefined) {width = 15;} - if (height === undefined) {height = 15;} - if (this.linegraph.groups[groupId] !== undefined) { - return this.linegraph.groups[groupId].getLegend(width,height); - } - else { - return "cannot find group:" + groupId; - } - } + /** - * This checks if the visible option of the supplied group (by ID) is true or false. - * @param groupId - * @returns {*} + * Filter the data based on the current filter + * @param {Array} data + * @return {Array} dataPoints Array with point objects which can be drawn on screen */ - Graph2d.prototype.isGroupVisible = function(groupId) { - if (this.linegraph.groups[groupId] !== undefined) { - return (this.linegraph.groups[groupId].visible && (this.linegraph.options.groups.visibility[groupId] === undefined || this.linegraph.options.groups.visibility[groupId] == true)); - } - else { - return false; - } - } + 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; + var dataPoints = []; - /** - * Get the data range of the item set. - * @returns {{min: Date, max: Date}} range A range with a start and end Date. - * When no minimum is found, min==null - * When no maximum is found, max==null - */ - Graph2d.prototype.getItemRange = function() { - var min = null; - var max = null; + 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 - // calculate min from start filed - for (var groupId in this.linegraph.groups) { - if (this.linegraph.groups.hasOwnProperty(groupId)) { - if (this.linegraph.groups[groupId].visible == true) { - for (var i = 0; i < this.linegraph.groups[groupId].itemsData.length; i++) { - var item = this.linegraph.groups[groupId].itemsData[i]; - var value = util.convert(item.x, 'Date').valueOf(); - min = min == null ? value : min > value ? value : min; - max = max == null ? value : max < value ? value : max; - } + // create two lists with all present x and y values + var dataX = []; + var dataY = []; + for (i = 0; i < this.getNumberOfRows(data); i++) { + x = data[i][this.colX] || 0; + y = data[i][this.colY] || 0; + + if (dataX.indexOf(x) === -1) { + dataX.push(x); + } + if (dataY.indexOf(y) === -1) { + dataY.push(y); } } - } - return { - min: (min != null) ? new Date(min) : null, - max: (max != null) ? new Date(max) : null - }; - }; + var sortNumber = function (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); - module.exports = Graph2d; + if (dataMatrix[xIndex] === undefined) { + dataMatrix[xIndex] = []; + } + var point3d = new Point3d(); + point3d.x = x; + point3d.y = y; + point3d.z = z; -/***/ }, -/* 15 */ -/***/ function(module, exports, __webpack_require__) { + obj = {}; + obj.point = point3d; + obj.trans = undefined; + obj.screen = undefined; + obj.bottom = new Point3d(x, y, this.zMin); - /** - * Created by Alex on 10/3/2014. - */ - var moment = __webpack_require__(44); + dataMatrix[xIndex][yIndex] = obj; + dataPoints.push(obj); + } - /** - * used in Core to convert the options into a volatile variable - * - * @param Core - */ - exports.convertHiddenOptions = function(body, hiddenDates) { - body.hiddenDates = []; - if (hiddenDates) { - if (Array.isArray(hiddenDates) == true) { - for (var i = 0; i < hiddenDates.length; i++) { - if (hiddenDates[i].repeat === undefined) { - var dateItem = {}; - dateItem.start = moment(hiddenDates[i].start).toDate().valueOf(); - dateItem.end = moment(hiddenDates[i].end).toDate().valueOf(); - body.hiddenDates.push(dateItem); + // 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; } } - body.hiddenDates.sort(function (a, b) { - return a.start - b.start; - }); // sort by start time } } - }; - - - /** - * create new entrees for the repeating hidden dates - * @param body - * @param hiddenDates - */ - exports.updateHiddenDates = function (body, hiddenDates) { - if (hiddenDates && body.domProps.centerContainer.width !== undefined) { - exports.convertHiddenOptions(body, hiddenDates); + 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; - var start = moment(body.range.start); - var end = moment(body.range.end); + if (this.colValue !== undefined) { + point.value = data[i][this.colValue] || 0; + } - var totalRange = (body.range.end - body.range.start); - var pixelTime = totalRange / body.domProps.centerContainer.width; + obj = {}; + obj.point = point; + obj.bottom = new Point3d(point.x, point.y, this.zMin); + obj.trans = undefined; + obj.screen = undefined; - for (var i = 0; i < hiddenDates.length; i++) { - if (hiddenDates[i].repeat !== undefined) { - var startDate = moment(hiddenDates[i].start); - var endDate = moment(hiddenDates[i].end); + dataPoints.push(obj); + } + } - if (startDate._d == "Invalid Date") { - throw new Error("Supplied start date is not valid: " + hiddenDates[i].start); - } - if (endDate._d == "Invalid Date") { - throw new Error("Supplied end date is not valid: " + hiddenDates[i].end); - } + return dataPoints; + }; - var duration = endDate - startDate; - if (duration >= 4 * pixelTime) { + /** + * 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); + } - var offset = 0; - var runUntil = end.clone(); - switch (hiddenDates[i].repeat) { - case "daily": // case of time - if (startDate.day() != endDate.day()) { - offset = 1; - } - startDate.dayOfYear(start.dayOfYear()); - startDate.year(start.year()); - startDate.subtract(7,'days'); + this.frame = document.createElement('div'); + this.frame.style.position = 'relative'; + this.frame.style.overflow = 'hidden'; - endDate.dayOfYear(start.dayOfYear()); - endDate.year(start.year()); - endDate.subtract(7 - offset,'days'); + // 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); + } - runUntil.add(1, 'weeks'); - break; - case "weekly": - var dayOffset = endDate.diff(startDate,'days') - var day = startDate.day(); + 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); - // set the start date to the range.start - startDate.date(start.date()); - startDate.month(start.month()); - startDate.year(start.year()); - endDate = startDate.clone(); + // 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' - // force - startDate.day(day); - endDate.day(day); - endDate.add(dayOffset,'days'); + 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); - startDate.subtract(1,'weeks'); - endDate.subtract(1,'weeks'); + // add the new graph to the container element + this.containerElement.appendChild(this.frame); + }; - runUntil.add(1, 'weeks'); - break - case "monthly": - if (startDate.month() != endDate.month()) { - offset = 1; - } - startDate.month(start.month()); - startDate.year(start.year()); - startDate.subtract(1,'months'); - endDate.month(start.month()); - endDate.year(start.year()); - endDate.subtract(1,'months'); - endDate.add(offset,'months'); + /** + * 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; - runUntil.add(1, 'months'); - break; - case "yearly": - if (startDate.year() != endDate.year()) { - offset = 1; - } - startDate.year(start.year()); - startDate.subtract(1,'years'); - endDate.year(start.year()); - endDate.subtract(1,'years'); - endDate.add(offset,'years'); + this._resizeCanvas(); + }; - runUntil.add(1, 'years'); - break; - default: - console.log("Wrong repeat format, allowed are: daily, weekly, monthly, yearly. Given:", hiddenDates[i].repeat); - return; - } - while (startDate < runUntil) { - body.hiddenDates.push({start: startDate.valueOf(), end: endDate.valueOf()}); - switch (hiddenDates[i].repeat) { - case "daily": - startDate.add(1, 'days'); - endDate.add(1, 'days'); - break; - case "weekly": - startDate.add(1, 'weeks'); - endDate.add(1, 'weeks'); - break - case "monthly": - startDate.add(1, 'months'); - endDate.add(1, 'months'); - break; - case "yearly": - startDate.add(1, 'y'); - endDate.add(1, 'y'); - break; - default: - console.log("Wrong repeat format, allowed are: daily, weekly, monthly, yearly. Given:", hiddenDates[i].repeat); - return; - } - } - body.hiddenDates.push({start: startDate.valueOf(), end: endDate.valueOf()}); - } - } - } - // remove duplicates, merge where possible - exports.removeDuplicates(body); - // ensure the new positions are not on hidden dates - var startHidden = exports.isHidden(body.range.start, body.hiddenDates); - var endHidden = exports.isHidden(body.range.end,body.hiddenDates); - var rangeStart = body.range.start; - var rangeEnd = body.range.end; - if (startHidden.hidden == true) {rangeStart = body.range.startToFront == true ? startHidden.startDate - 1 : startHidden.endDate + 1;} - if (endHidden.hidden == true) {rangeEnd = body.range.endToFront == true ? endHidden.startDate - 1 : endHidden.endDate + 1;} - if (startHidden.hidden == true || endHidden.hidden == true) { - body.range._applyRange(rangeStart, rangeEnd); - } - } + /** + * 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%'; - } + 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'; + }; /** - * remove duplicates from the hidden dates list. Duplicates are evil. They mess everything up. - * Scales with N^2 - * @param body + * Start animation */ - exports.removeDuplicates = function(body) { - var hiddenDates = body.hiddenDates; - var safeDates = []; - for (var i = 0; i < hiddenDates.length; i++) { - for (var j = 0; j < hiddenDates.length; j++) { - if (i != j && hiddenDates[j].remove != true && hiddenDates[i].remove != true) { - // j inside i - if (hiddenDates[j].start >= hiddenDates[i].start && hiddenDates[j].end <= hiddenDates[i].end) { - hiddenDates[j].remove = true; - } - // j start inside i - else if (hiddenDates[j].start >= hiddenDates[i].start && hiddenDates[j].start <= hiddenDates[i].end) { - hiddenDates[i].end = hiddenDates[j].end; - hiddenDates[j].remove = true; - } - // j end inside i - else if (hiddenDates[j].end >= hiddenDates[i].start && hiddenDates[j].end <= hiddenDates[i].end) { - hiddenDates[i].start = hiddenDates[j].start; - hiddenDates[j].remove = true; - } - } - } - } - - for (var i = 0; i < hiddenDates.length; i++) { - if (hiddenDates[i].remove !== true) { - safeDates.push(hiddenDates[i]); - } - } + Graph3d.prototype.animationStart = function() { + if (!this.frame.filter || !this.frame.filter.slider) + throw 'No animation available'; - body.hiddenDates = safeDates; - body.hiddenDates.sort(function (a, b) { - return a.start - b.start; - }); // sort by start time - } + this.frame.filter.slider.play(); + }; - exports.printDates = function(dates) { - for (var i =0; i < dates.length; i++) { - console.log(i, new Date(dates[i].start),new Date(dates[i].end), dates[i].start, dates[i].end, dates[i].remove); - } - } /** - * Used in TimeStep to avoid the hidden times. - * @param timeStep - * @param previousTime + * Stop animation */ - exports.stepOverHiddenDates = function(timeStep, previousTime) { - var stepInHidden = false; - var currentValue = timeStep.current.valueOf(); - for (var i = 0; i < timeStep.hiddenDates.length; i++) { - var startDate = timeStep.hiddenDates[i].start; - var endDate = timeStep.hiddenDates[i].end; - if (currentValue >= startDate && currentValue < endDate) { - stepInHidden = true; - break; - } - } - - if (stepInHidden == true && currentValue < timeStep._end.valueOf() && currentValue != previousTime) { - var prevValue = moment(previousTime); - var newValue = moment(endDate); - //check if the next step should be major - if (prevValue.year() != newValue.year()) {timeStep.switchedYear = true;} - else if (prevValue.month() != newValue.month()) {timeStep.switchedMonth = true;} - else if (prevValue.dayOfYear() != newValue.dayOfYear()) {timeStep.switchedDay = true;} + Graph3d.prototype.animationStop = function() { + if (!this.frame.filter || !this.frame.filter.slider) return; - timeStep.current = newValue.toDate(); - } + this.frame.filter.slider.stop(); }; - ///** - // * Used in TimeStep to avoid the hidden times. - // * @param timeStep - // * @param previousTime - // */ - //exports.checkFirstStep = function(timeStep) { - // var stepInHidden = false; - // var currentValue = timeStep.current.valueOf(); - // for (var i = 0; i < timeStep.hiddenDates.length; i++) { - // var startDate = timeStep.hiddenDates[i].start; - // var endDate = timeStep.hiddenDates[i].end; - // if (currentValue >= startDate && currentValue < endDate) { - // stepInHidden = true; - // break; - // } - // } - // - // if (stepInHidden == true && currentValue <= timeStep._end.valueOf()) { - // var newValue = moment(endDate); - // timeStep.current = newValue.toDate(); - // } - //}; - /** - * replaces the Core toScreen methods - * @param Core - * @param time - * @param width - * @returns {number} + * 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 */ - exports.toScreen = function(Core, time, width) { - if (Core.body.hiddenDates.length == 0) { - var conversion = Core.range.conversion(width); - return (time.valueOf() - conversion.offset) * conversion.scale; + 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 { - var hidden = exports.isHidden(time, Core.body.hiddenDates) - if (hidden.hidden == true) { - time = hidden.startDate; - } - - var duration = exports.getHiddenDurationBetween(Core.body.hiddenDates, Core.range.start, Core.range.end); - time = exports.correctTimeForHidden(Core.body.hiddenDates, Core.range, time); + this.xcenter = parseFloat(this.defaultXCenter); // supposed to be in px + } - var conversion = Core.range.conversion(width, duration); - return (time.valueOf() - conversion.offset) * conversion.scale; + // 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 } }; - /** - * Replaces the core toTime methods - * @param body - * @param range - * @param x - * @param width - * @returns {Date} + * 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. */ - exports.toTime = function(Core, x, width) { - if (Core.body.hiddenDates.length == 0) { - var conversion = Core.range.conversion(width); - return new Date(x / conversion.scale + conversion.offset); + Graph3d.prototype.setCameraPosition = function(pos) { + if (pos === undefined) { + return; } - else { - var hiddenDuration = exports.getHiddenDurationBetween(Core.body.hiddenDates, Core.range.start, Core.range.end); - var totalDuration = Core.range.end - Core.range.start - hiddenDuration; - var partialDuration = totalDuration * x / width; - var accumulatedHiddenDuration = exports.getAccumulatedHiddenDuration(Core.body.hiddenDates, Core.range, partialDuration); - var newTime = new Date(accumulatedHiddenDuration + partialDuration + Core.range.start); - return newTime; + 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(); }; /** - * Support function - * - * @param hiddenDates - * @param range - * @returns {number} + * Retrieve the current camera rotation + * @return {object} An object with parameters horizontal, vertical, and + * distance */ - exports.getHiddenDurationBetween = function(hiddenDates, start, end) { - var duration = 0; - for (var i = 0; i < hiddenDates.length; i++) { - var startDate = hiddenDates[i].start; - var endDate = hiddenDates[i].end; - // if time after the cutout, and the - if (startDate >= start && endDate < end) { - duration += endDate - startDate; - } - } - return duration; + Graph3d.prototype.getCameraPosition = function() { + var pos = this.camera.getArmRotation(); + pos.distance = this.camera.getArmLength(); + return pos; }; - /** - * Support function - * @param hiddenDates - * @param range - * @param time - * @returns {{duration: number, time: *, offset: number}} + * Load data into the 3D Graph */ - exports.correctTimeForHidden = function(hiddenDates, range, time) { - time = moment(time).toDate().valueOf(); - time -= exports.getHiddenDurationBefore(hiddenDates,range,time); - return time; - }; + Graph3d.prototype._readData = function(data) { + // read the data + this._dataInitialize(data, this.style); - exports.getHiddenDurationBefore = function(hiddenDates, range, time) { - var timeOffset = 0; - time = moment(time).toDate().valueOf(); - for (var i = 0; i < hiddenDates.length; i++) { - var startDate = hiddenDates[i].start; - var endDate = hiddenDates[i].end; - // if time after the cutout, and the - if (startDate >= range.start && endDate < range.end) { - if (time >= endDate) { - timeOffset += (endDate - startDate); - } - } + if (this.dataFilter) { + // apply filtering + this.dataPoints = this.dataFilter._getDataPoints(); } - return timeOffset; - } - - /** - * sum the duration from start to finish, including the hidden duration, - * until the required amount has been reached, return the accumulated hidden duration - * @param hiddenDates - * @param range - * @param time - * @returns {{duration: number, time: *, offset: number}} - */ - exports.getAccumulatedHiddenDuration = function(hiddenDates, range, requiredDuration) { - var hiddenDuration = 0; - var duration = 0; - var previousPoint = range.start; - //exports.printDates(hiddenDates) - for (var i = 0; i < hiddenDates.length; i++) { - var startDate = hiddenDates[i].start; - var endDate = hiddenDates[i].end; - // if time after the cutout, and the - if (startDate >= range.start && endDate < range.end) { - duration += startDate - previousPoint; - previousPoint = endDate; - if (duration >= requiredDuration) { - break; - } - else { - hiddenDuration += endDate - startDate; - } - } + else { + // no filtering. load all data + this.dataPoints = this._getDataPoints(this.dataTable); } - return hiddenDuration; + // draw the filter + this._redrawFilter(); }; + /** + * 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(); + } + }; /** - * used to step over to either side of a hidden block. Correction is disabled on tablets, might be set to true - * @param hiddenDates - * @param time - * @param direction - * @param correctionEnabled - * @returns {*} + * Update the options. Options will be merged with current options + * @param {Object} options */ - exports.snapAwayFromHidden = function(hiddenDates, time, direction, correctionEnabled) { - var isHidden = exports.isHidden(time, hiddenDates); - if (isHidden.hidden == true) { - if (direction < 0) { - if (correctionEnabled == true) { - return isHidden.startDate - (isHidden.endDate - time) - 1; - } - else { - return isHidden.startDate - 1; - } - } - else { - if (correctionEnabled == true) { - return isHidden.endDate + (time - isHidden.startDate) + 1; - } - else { - return isHidden.endDate + 1; - } - } - } - else { - return time; - } - - } + Graph3d.prototype.setOptions = function (options) { + var cameraPosition = undefined; + this.animationStop(); - /** - * Check if a time is hidden - * - * @param time - * @param hiddenDates - * @returns {{hidden: boolean, startDate: Window.start, endDate: *}} - */ - exports.isHidden = function(time, hiddenDates) { - for (var i = 0; i < hiddenDates.length; i++) { - var startDate = hiddenDates[i].start; - var endDate = hiddenDates[i].end; + if (options !== undefined) { + // retrieve parameter values + if (options.width !== undefined) this.width = options.width; + if (options.height !== undefined) this.height = options.height; - if (time >= startDate && time < endDate) { // if the start is entering a hidden zone - return {hidden: true, startDate: startDate, endDate: endDate}; - break; - } - } - return {hidden: false, startDate: startDate, endDate: endDate}; - } + if (options.xCenter !== undefined) this.defaultXCenter = options.xCenter; + if (options.yCenter !== undefined) this.defaultYCenter = options.yCenter; -/***/ }, -/* 16 */ -/***/ function(module, exports, __webpack_require__) { + 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; - /** - * @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, customRange, alignZeros) { - // variables - this.current = 0; + if (options.xValueLabel !== undefined) this.xValueLabel = options.xValueLabel; + if (options.yValueLabel !== undefined) this.yValueLabel = options.yValueLabel; + if (options.zValueLabel !== undefined) this.zValueLabel = options.zValueLabel; - this.autoScale = true; - this.stepIndex = 0; - this.step = 1; - this.scale = 1; + 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; - this.marginStart; - this.marginEnd; - this.deadSpace = 0; + if (options.animationInterval !== undefined) this.animationInterval = options.animationInterval; + if (options.animationPreload !== undefined) this.animationPreload = options.animationPreload; + if (options.animationAutoStart !== undefined)this.animationAutoStart = options.animationAutoStart; - this.majorSteps = [1, 2, 5, 10]; - this.minorSteps = [0.25, 0.5, 1, 2]; + if (options.xBarWidth !== undefined) this.defaultXBarWidth = options.xBarWidth; + if (options.yBarWidth !== undefined) this.defaultYBarWidth = options.yBarWidth; - this.alignZeros = alignZeros; + 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; - this.setRange(start, end, minimumStep, containerHeight, customRange); - } + if (options.cameraPosition !== undefined) cameraPosition = options.cameraPosition; + 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); + } + } + this._setBackgroundColor(options && options.backgroundColor); - /** - * 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, customRange) { - this._start = customRange.min === undefined ? start : customRange.min; - this._end = customRange.max === undefined ? end : customRange.max; + this.setSize(this.width, this.height); - if (this._start == this._end) { - this._start -= 0.75; - this._end += 1; + // re-load the data + if (this.dataTable) { + this.setData(this.dataTable); } - if (this.autoScale == true) { - this.setMinimumStep(minimumStep, containerHeight); + // start animation when option is true + if (this.animationAutoStart && this.dataFilter) { + this.animationStart(); } - - this.setFirst(customRange); }; /** - * Automatically determine the scale that bests fits the provided minimum step - * @param {Number} [minimumStep] The minimum step size in milliseconds + * Redraw the Graph. */ - DataStep.prototype.setMinimumStep = function(minimumStep, containerHeight) { - // round to floor - var size = this._end - this._start; - var safeSize = size * 1.2; - var minimumStepValue = minimumStep * (safeSize / containerHeight); - var orderOfMagnitude = Math.round(Math.log(safeSize)/Math.LN10); + Graph3d.prototype.redraw = function() { + if (this.dataPoints === undefined) { + throw 'Error: graph data not initialized'; + } - var minorStepIdx = -1; - var magnitudefactor = Math.pow(10,orderOfMagnitude); + this._resizeCanvas(); + this._resizeCenter(); + this._redrawSlider(); + this._redrawClear(); + this._redrawAxis(); - var start = 0; - if (orderOfMagnitude < 0) { - start = orderOfMagnitude; + if (this.style === Graph3d.STYLE.GRID || + this.style === Graph3d.STYLE.SURFACE) { + this._redrawDataGrid(); } - - var solutionFound = false; - for (var i = start; Math.abs(i) <= Math.abs(orderOfMagnitude); i++) { - magnitudefactor = Math.pow(10,i); - for (var j = 0; j < this.minorSteps.length; j++) { - var stepSize = magnitudefactor * this.minorSteps[j]; - if (stepSize >= minimumStepValue) { - solutionFound = true; - minorStepIdx = j; - break; - } - } - if (solutionFound == true) { - break; - } + else if (this.style === Graph3d.STYLE.LINE) { + this._redrawDataLine(); } - this.stepIndex = minorStepIdx; - this.scale = magnitudefactor; - this.step = magnitudefactor * this.minorSteps[minorStepIdx]; + 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(); }; + /** + * Clear the canvas before redrawing + */ + Graph3d.prototype._redrawClear = function() { + var canvas = this.frame.canvas; + var ctx = canvas.getContext('2d'); + + ctx.clearRect(0, 0, canvas.width, canvas.height); + }; /** - * Round the current date to the first minor date value - * This must be executed once when the current date is set to start Date + * Redraw the legend showing the colors */ - DataStep.prototype.setFirst = function(customRange) { - if (customRange === undefined) { - customRange = {}; - } + Graph3d.prototype._redrawLegend = function() { + var y; - var niceStart = customRange.min === undefined ? this._start - (this.scale * 2 * this.minorSteps[this.stepIndex]) : customRange.min; - var niceEnd = customRange.max === undefined ? this._end + (this.scale * this.minorSteps[this.stepIndex]) : customRange.max; + if (this.style === Graph3d.STYLE.DOTCOLOR || + this.style === Graph3d.STYLE.DOTSIZE) { - this.marginEnd = customRange.max === undefined ? this.roundToMinor(niceEnd) : customRange.max; - this.marginStart = customRange.min === undefined ? this.roundToMinor(niceStart) : customRange.min; + var dotSize = this.frame.clientWidth * 0.02; - // if we need to align the zero's we need to make sure that there is a zero to use. - if (this.alignZeros == true && (this.marginEnd - this.marginStart) % this.step != 0) { - this.marginEnd += this.marginEnd % this.step; + var widthMin, widthMax; + if (this.style === Graph3d.STYLE.DOTSIZE) { + widthMin = dotSize / 2; // px + widthMax = dotSize / 2 + dotSize * 2; // Todo: put this in one function + } + else { + widthMin = 20; // px + widthMax = 20; // px + } + + var height = Math.max(this.frame.clientHeight * 0.25, 100); + var top = this.margin; + var right = this.frame.clientWidth - this.margin; + var left = right - widthMax; + var bottom = top + height; } - this.deadSpace = this.roundToMinor(niceEnd) - niceEnd + this.roundToMinor(niceStart) - niceStart; - this.marginRange = this.marginEnd - this.marginStart; + var canvas = this.frame.canvas; + var ctx = canvas.getContext('2d'); + ctx.lineWidth = 1; + ctx.font = '14px arial'; // TODO: put in options + if (this.style === Graph3d.STYLE.DOTCOLOR) { + // draw the color bar + var ymin = 0; + var ymax = height; // Todo: make height customizable + for (y = ymin; y < ymax; y++) { + var f = (y - ymin) / (ymax - ymin); - this.current = this.marginEnd; - }; + //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); - 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]); + ctx.strokeStyle = color; + ctx.beginPath(); + ctx.moveTo(left, top + y); + ctx.lineTo(right, top + y); + ctx.stroke(); + } + + ctx.strokeStyle = this.colorAxis; + ctx.strokeRect(left, top, widthMax, height); } - else { - return rounded; + + 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(); } - } + 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(); - /** - * 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); - }; + ctx.textAlign = 'right'; + ctx.textBaseline = 'middle'; + ctx.fillStyle = this.colorAxis; + ctx.fillText(step.getCurrent(), left - 2 * gridLineLen, y); - /** - * Do the next step - */ - DataStep.prototype.next = function() { - var prev = this.current; - this.current -= this.step; + step.next(); + } - // safety mechanism: if current time is still unchanged, move to the end - if (this.current == prev) { - this.current = this._end; + ctx.textAlign = 'right'; + ctx.textBaseline = 'top'; + var label = this.legendLabel; + ctx.fillText(label, right, bottom + this.margin); } }; /** - * Do the next step + * Redraw the filter */ - DataStep.prototype.previous = function() { - this.current += this.step; - this.marginEnd += this.step; - this.marginRange = this.marginEnd - this.marginStart; - }; + 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'; - /** - * Get the current datetime - * @return {String} current The current date - */ - DataStep.prototype.getCurrent = function(decimals) { - // prevent round-off errors when close to zero - var current = (Math.abs(this.current) < this.step / 2) ? 0 : this.current; - var toPrecision = '' + Number(current).toPrecision(5); + slider.setValues(this.dataFilter.values); + slider.setPlayInterval(this.animationInterval); - // If decimals is specified, then limit or extend the string as required - if(decimals !== undefined && !isNaN(Number(decimals))) { - // If string includes exponent, then we need to add it to the end - var exp = ""; - var index = toPrecision.indexOf("e"); - if(index != -1) { - // Get the exponent - exp = toPrecision.slice(index); - // Remove the exponent in case we need to zero-extend - toPrecision = toPrecision.slice(0, index); - } - index = Math.max(toPrecision.indexOf(","), toPrecision.indexOf(".")); - if(index === -1) { - // No decimal found - if we want decimals, then we need to add it - if(decimals !== 0) { - toPrecision += '.'; - } - // Calculate how long the string should be - index = toPrecision.length + decimals; - } - else if(decimals !== 0) { - // Calculate how long the string should be - accounting for the decimal place - index += decimals + 1; - } - if(index > toPrecision.length) { - // We need to add zeros! - for(var cnt = index - toPrecision.length; cnt > 0; cnt--) { - toPrecision += '0'; - } - } - else { - // we need to remove characters - toPrecision = toPrecision.slice(0, index); - } - // Add the exponent if there is one - toPrecision += exp; + // create an event handler + var me = this; + var onchange = function () { + var index = slider.getIndex(); + + me.dataFilter.selectValue(index); + me.dataPoints = me.dataFilter._getDataPoints(); + + me.redraw(); + }; + slider.setOnChangeCallback(onchange); } else { - if (toPrecision.indexOf(",") != -1 || toPrecision.indexOf(".") != -1) { - // If no decimal is specified, and there are decimal places, remove trailing zeros - 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; - } - } - } + this.frame.filter.slider = undefined; } - - return toPrecision; }; /** - * 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. + * Redraw the slider */ - DataStep.prototype.isMajor = function() { - return (this.current % (this.scale * this.majorSteps[this.stepIndex]) == 0); + Graph3d.prototype._redrawSlider = function() { + if ( this.frame.filter.slider !== undefined) { + this.frame.filter.slider.redraw(); + } }; - module.exports = DataStep; + /** + * Redraw common information + */ + Graph3d.prototype._redrawInfo = function() { + if (this.dataFilter) { + var canvas = this.frame.canvas; + var ctx = canvas.getContext('2d'); + + ctx.font = '14px arial'; // TODO: put in options + ctx.lineStyle = 'gray'; + ctx.fillStyle = 'gray'; + ctx.textAlign = 'left'; + ctx.textBaseline = 'top'; -/***/ }, -/* 17 */ -/***/ function(module, exports, __webpack_require__) { + var x = this.margin; + var y = this.margin; + ctx.fillText(this.dataFilter.getLabel() + ': ' + this.dataFilter.getSelectedValue(), x, y); + } + }; - var util = __webpack_require__(1); - var hammerUtil = __webpack_require__(47); - var moment = __webpack_require__(44); - var Component = __webpack_require__(20); - var DateUtil = __webpack_require__(15); /** - * @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 + * Redraw the axis */ - function Range(body, options) { - var now = moment().hours(0).minutes(0).seconds(0).milliseconds(0); - this.start = now.clone().add(-3, 'days').valueOf(); // Number - this.end = now.clone().add(4, 'days').valueOf(); // Number + 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; - this.body = body; - this.deltaDifference = 0; - this.scaleOffset = 0; - this.startToFront = false; - this.endToFront = true; + // TODO: get the actual rendered style of the containerElement + //ctx.font = this.containerElement.style.font; + ctx.font = 24 / this.camera.getArmLength() + 'px arial'; - // 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); - - this.props = { - touch: {} - }; - this.animateTimer = null; + // 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; - // 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)); + // 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(); - // ignore dragging when holding - this.body.emitter.on('hold', this._onHold.bind(this)); + 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(); - // mouse wheel for zooming - this.body.emitter.on('mousewheel', this._onMouseWheel.bind(this)); - this.body.emitter.on('DOMMouseScroll', this._onMouseWheel.bind(this)); // For FF + 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(); + } - // pinch to zoom - this.body.emitter.on('touch', this._onTouch.bind(this)); - this.body.emitter.on('pinch', this._onPinch.bind(this)); + 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'; + } + ctx.fillStyle = this.colorAxis; + ctx.fillText(' ' + this.xValueLabel(step.getCurrent()) + ' ', text.x, text.y); - this.setOptions(options); - } + step.next(); + } - Range.prototype = new Component(); + // 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(); - /** - * 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 - */ - Range.prototype.setOptions = function (options) { - if (options) { - // copy the options that we know - var fields = ['direction', 'min', 'max', 'zoomMin', 'zoomMax', 'moveable', 'zoomable', 'activate', 'hiddenDates']; - util.selectiveExtend(fields, this.options, options); + 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(); + } - if ('start' in options || 'end' in options) { - // apply a new range. both start and end are optional - this.setRange(options.start, options.end); + 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(' ' + this.yValueLabel(step.getCurrent()) + ' ', text.x, text.y); - /** - * 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".'); + step.next(); } - } - /** - * Set a new start and end range - * @param {Date | Number | String} [start] - * @param {Date | Number | String} [end] - * @param {boolean | number} [animate=false] If true, the range is animated - * smoothly to the new window. - * If animate is a number, the - * number is taken as duration - * Default duration is 500 ms. - * @param {Boolean} [byUser=false] - * - */ - Range.prototype.setRange = function(start, end, animate, byUser) { - if (byUser !== true) { - byUser = false; + // 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(); } - var _start = start != undefined ? util.convert(start, 'Date').valueOf() : null; - var _end = end != undefined ? util.convert(end, 'Date').valueOf() : null; - this._cancelAnimation(); + 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(); - if (animate) { - var me = this; - var initStart = this.start; - var initEnd = this.end; - var duration = typeof animate === 'number' ? animate : 500; - var initTime = new Date().valueOf(); - var anyChanged = false; + ctx.textAlign = 'right'; + ctx.textBaseline = 'middle'; + ctx.fillStyle = this.colorAxis; + ctx.fillText(this.zValueLabel(step.getCurrent()) + ' ', from.x - 5, from.y); - var next = function () { - if (!me.props.touch.dragging) { - var now = new Date().valueOf(); - var time = now - initTime; - var done = time > duration; - var s = (done || _start === null) ? _start : util.easeInOutQuad(time, initStart, _start, duration); - var e = (done || _end === null) ? _end : util.easeInOutQuad(time, initEnd, _end, duration); + 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(); - changed = me._applyRange(s, e); - DateUtil.updateHiddenDates(me.body, me.options.hiddenDates); - anyChanged = anyChanged || changed; - if (changed) { - me.body.emitter.emit('rangechange', {start: new Date(me.start), end: new Date(me.end), byUser:byUser}); - } + // 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(); - if (done) { - if (anyChanged) { - me.body.emitter.emit('rangechanged', {start: new Date(me.start), end: new Date(me.end), byUser:byUser}); - } - } - else { - // animate with as high as possible frame rate, leave 20 ms in between - // each to prevent the browser from blocking - me.animateTimer = setTimeout(next, 20); - } - } - }; + // 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(); - return next(); + // 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 { - var changed = this._applyRange(_start, _end); - DateUtil.updateHiddenDates(this.body, this.options.hiddenDates); - if (changed) { - var params = {start: new Date(this.start), end: new Date(this.end), byUser:byUser}; - this.body.emitter.emit('rangechange', params); - this.body.emitter.emit('rangechanged', params); + + // 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); } }; /** - * Stop an animation - * @private + * 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 */ - Range.prototype._cancelAnimation = function () { - if (this.animateTimer) { - clearTimeout(this.animateTimer); - this.animateTimer = null; + 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; } + + return 'RGB(' + parseInt(R*255) + ',' + parseInt(G*255) + ',' + parseInt(B*255) + ')'; }; + /** - * 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 + * Draw all datapoints as a grid + * This function can be used when the style is 'grid' */ - 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; + 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; - // 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 + '"'); - } - // prevent start < end - if (newEnd < newStart) { - newEnd = newStart; + if (this.dataPoints === undefined || this.dataPoints.length <= 0) + return; // TODO: throw exception? + + // calculate the translations and screen position of all points + for (i = 0; i < this.dataPoints.length; i++) { + var trans = this._convertPointToTranslation(this.dataPoints[i].point); + var screen = this._convertTranslationToScreen(trans); + + this.dataPoints[i].trans = trans; + this.dataPoints[i].screen = screen; + + // 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; } - // prevent start < min - if (min !== null) { - if (newStart < min) { - diff = (min - newStart); - newStart += diff; - newEnd += diff; + // sort the points on depth of their (x,y) position (not on z) + var sortDepth = function (a, b) { + return b.dist - a.dist; + }; + this.dataPoints.sort(sortDepth); - // prevent end > max - if (max != null) { - if (newEnd > max) { - newEnd = max; + if (this.style === Graph3d.STYLE.SURFACE) { + for (i = 0; i < this.dataPoints.length; i++) { + point = this.dataPoints[i]; + right = this.dataPoints[i].pointRight; + top = this.dataPoints[i].pointTop; + cross = this.dataPoints[i].pointCross; + + if (point !== undefined && right !== undefined && top !== undefined && cross !== undefined) { + + if (this.showGrayBottom || this.showShadow) { + // calculate the cross product of the two vectors from center + // to left and right, in order to know whether we are looking at the + // bottom or at the top side. We can also use the cross product + // for calculating light intensity + var aDiff = Point3d.subtract(cross.trans, point.trans); + var bDiff = Point3d.subtract(top.trans, right.trans); + var crossproduct = Point3d.crossProduct(aDiff, bDiff); + var len = crossproduct.length(); + // FIXME: there is a bug with determining the surface side (shadow or colored) + + topSideVisible = (crossproduct.z > 0); + } + else { + topSideVisible = true; } - } - } - } - // prevent end > max - if (max !== null) { - if (newEnd > max) { - diff = (newEnd - max); - newStart -= diff; - newEnd -= diff; + 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 - // prevent start < min - if (min != null) { - if (newStart < min) { - newStart = min; + 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(); } } } - - // 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 && newStart > this.start && newEnd < this.end) { - // 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; + else { // grid style + for (i = 0; i < this.dataPoints.length; i++) { + point = this.dataPoints[i]; + right = this.dataPoints[i].pointRight; + top = this.dataPoints[i].pointTop; + + if (point !== undefined) { + if (this.showPerspective) { + lineWidth = 2 / -point.trans.z; + } + else { + lineWidth = 2 * -(this.eye.z / this.camera.getArmLength()); + } } - } - } - // prevent (end-start) > zoomMax - if (this.options.zoomMax !== null) { - var zoomMax = parseFloat(this.options.zoomMax); - if (zoomMax < 0) { - zoomMax = 0; - } + 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; - if ((newEnd - newStart) > zoomMax) { - if ((this.end - this.start) === zoomMax && newStart < this.start && newEnd > this.end) { - // 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; + ctx.lineWidth = lineWidth; + ctx.strokeStyle = this._hsv2rgb(h, 1, 1); + ctx.beginPath(); + ctx.moveTo(point.screen.x, point.screen.y); + ctx.lineTo(right.screen.x, right.screen.y); + ctx.stroke(); } - } - } - var changed = (this.start != newStart || this.end != newEnd); + 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; - // if the new range does NOT overlap with the old range, emit checkRangedItems to avoid not showing ranged items (ranged meaning has end time, not necessarily of type Range) - if (!((newStart >= this.start && newStart <= this.end) || (newEnd >= this.start && newEnd <= this.end)) && - !((this.start >= newStart && this.start <= newEnd) || (this.end >= newStart && this.end <= newEnd) )) { - this.body.emitter.emit('checkRangedItems'); + 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(); + } + } } - - this.start = newStart; - this.end = newEnd; - return changed; }; - /** - * Retrieve the current range. - * @return {Object} An object with start and end properties - */ - Range.prototype.getRange = function() { - return { - start: this.start, - end: this.end - }; - }; /** - * Calculate the conversion offset and scale for current range, based on - * the provided width - * @param {Number} width - * @returns {{offset: number, scale: number}} conversion + * Draw all datapoints as dots. + * This function can be used when the style is 'dot' or 'dot-line' */ - Range.prototype.conversion = function (width, totalHidden) { - return Range.conversion(this.start, this.end, width, totalHidden); - }; + Graph3d.prototype._redrawDataDot = function() { + var canvas = this.frame.canvas; + var ctx = canvas.getContext('2d'); + var i; - /** - * Static method to calculate the conversion offset and scale for a range, - * based on the provided start, end, and width - * @param {Number} start - * @param {Number} end - * @param {Number} width - * @returns {{offset: number, scale: number}} conversion - */ - Range.conversion = function (start, end, width, totalHidden) { - if (totalHidden === undefined) { - totalHidden = 0; + 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; } - if (width != 0 && (end - start != 0)) { - return { - offset: start, - scale: width / (end - start - totalHidden) + + // order the translated points by depth + var sortDepth = function (a, b) { + return b.dist - a.dist; + }; + this.dataPoints.sort(sortDepth); + + // 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(); } - } - else { - return { - offset: 0, - scale: 1 - }; + + // 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; + } + + var radius; + if (this.showPerspective) { + radius = size / -point.trans.z; + } + else { + radius = size * -(this.eye.z / this.camera.getArmLength()); + } + if (radius < 0) { + radius = 0; + } + + 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); + } + + // 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(); } }; /** - * Start dragging horizontally or vertically - * @param {Event} event - * @private + * Draw all datapoints as bars. + * This function can be used when the style is 'bar', 'bar-color', or 'bar-size' */ - Range.prototype._onDragStart = function(event) { - this.deltaDifference = 0; - this.previousDelta = 0; - // only allow dragging when configured as movable - if (!this.options.moveable) return; + Graph3d.prototype._redrawDataBar = function() { + var canvas = this.frame.canvas; + var ctx = canvas.getContext('2d'); + var i, j, surface, corners; - // 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; + if (this.dataPoints === undefined || this.dataPoints.length <= 0) + return; // TODO: throw exception? - this.props.touch.start = this.start; - this.props.touch.end = this.end; - this.props.touch.dragging = true; + // calculate the translations of all points + for (i = 0; i < this.dataPoints.length; i++) { + var trans = this._convertPointToTranslation(this.dataPoints[i].point); + var screen = this._convertTranslationToScreen(trans); + this.dataPoints[i].trans = trans; + this.dataPoints[i].screen = screen; - if (this.body.dom.root) { - this.body.dom.root.style.cursor = 'move'; + // 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; } - }; - /** - * Perform dragging operation - * @param {Event} event - * @private - */ - Range.prototype._onDrag = function (event) { - // only allow dragging when configured as movable - if (!this.options.moveable) return; - // refuse to drag when we where pinching to prevent the timeline make a jump - // when releasing the fingers in opposite order from the touch screen - if (!this.props.touch.allowDragging) return; + // order the translated points by depth + var sortDepth = function (a, b) { + return b.dist - a.dist; + }; + this.dataPoints.sort(sortDepth); - var direction = this.options.direction; - validateDirection(direction); + // 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]; - var delta = (direction == 'horizontal') ? event.gesture.deltaX : event.gesture.deltaY; - delta -= this.deltaDifference; - var interval = (this.props.touch.end - this.props.touch.start); + // 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); + } - // normalize dragging speed if cutout is in between. - var duration = DateUtil.getHiddenDurationBetween(this.body.hiddenDates, this.start, this.end); - interval -= duration; + // 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); + } - var width = (direction == 'horizontal') ? this.body.domProps.center.width : this.body.domProps.center.height; - var diffRange = -delta / width * interval; - var newStart = this.props.touch.start + diffRange; - var newEnd = this.props.touch.end + diffRange; + // 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); + }); - // snapping times away from hidden zones - var safeStart = DateUtil.snapAwayFromHidden(this.body.hiddenDates, newStart, this.previousDelta-delta, true); - var safeEnd = DateUtil.snapAwayFromHidden(this.body.hiddenDates, newEnd, this.previousDelta-delta, true); - if (safeStart != newStart || safeEnd != newEnd) { - this.deltaDifference += delta; - this.props.touch.start = safeStart; - this.props.touch.end = safeEnd; - this._onDrag(event); - return; - } + // 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; - this.previousDelta = delta; - this._applyRange(newStart, newEnd); + // 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}) + } - // fire a rangechange event - this.body.emitter.emit('rangechange', { - start: new Date(this.start), - end: new Date(this.end), - byUser: true - }); - }; + // order the surfaces by their (translated) depth + surfaces.sort(function (a, b) { + var diff = b.dist - a.dist; + if (diff) return diff; - /** - * Stop dragging operation - * @param {event} event - * @private - */ - Range.prototype._onDragEnd = function (event) { - // only allow dragging when configured as movable - if (!this.options.moveable) return; + // if equal depth, sort the top surface last + if (a.corners === top) return 1; + if (b.corners === top) return -1; - // 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; + // both are equal + return 0; + }); - this.props.touch.dragging = false; - if (this.body.dom.root) { - this.body.dom.root.style.cursor = 'auto'; + // 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(); + } } - - // fire a rangechanged event - this.body.emitter.emit('rangechanged', { - start: new Date(this.start), - end: new Date(this.end), - byUser: true - }); }; + /** - * Event handler for mouse wheel event, used to zoom - * Code from http://adomas.org/javascript-mouse-wheel/ - * @param {Event} event - * @private + * Draw a line through all datapoints. + * This function can be used when the style is 'line' */ - Range.prototype._onMouseWheel = function(event) { - // only allow zooming when configured as zoomable and moveable - if (!(this.options.zoomable && this.options.moveable)) return; + Graph3d.prototype._redrawDataLine = function() { + var canvas = this.frame.canvas, + ctx = canvas.getContext('2d'), + point, i; - // 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 (this.dataPoints === undefined || this.dataPoints.length <= 0) + return; // TODO: throw exception? - // 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 + // 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); - // 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)) ; - } + this.dataPoints[i].trans = trans; + this.dataPoints[i].screen = screen; + } - // 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); + // start the line + if (this.dataPoints.length > 0) { + point = this.dataPoints[0]; - this.zoom(scale, pointerDate, delta); + ctx.lineWidth = 1; // TODO: make customizable + ctx.strokeStyle = 'blue'; // TODO: make customizable + ctx.beginPath(); + ctx.moveTo(point.screen.x, point.screen.y); } - // Prevent default actions caused by mouse wheel - // (else the page and timeline both zoom and scroll) - event.preventDefault(); - }; - - /** - * 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; - this.scaleOffset = 0; - this.deltaDifference = 0; - }; + // 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); + } - /** - * On start of a hold gesture - * @private - */ - Range.prototype._onHold = function () { - this.props.touch.allowDragging = false; + // finish the line + if (this.dataPoints.length > 0) { + ctx.stroke(); + } }; /** - * Handle pinch event - * @param {Event} event - * @private + * Start a moving operation inside the provided parent element + * @param {Event} event The event that occurred (required for + * retrieving the mouse position) */ - Range.prototype._onPinch = function (event) { - // only allow zooming when configured as zoomable and moveable - if (!(this.options.zoomable && this.options.moveable)) return; + Graph3d.prototype._onMouseDown = function(event) { + event = event || window.event; - this.props.touch.allowDragging = false; + // 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 (event.gesture.touches.length > 1) { - if (!this.props.touch.center) { - this.props.touch.center = getPointer(event.gesture.center, this.body.dom.center); - } - - var scale = 1 / (event.gesture.scale + this.scaleOffset); - var centerDate = this._pointerToDate(this.props.touch.center); - - var hiddenDuration = DateUtil.getHiddenDurationBetween(this.body.hiddenDates, this.start, this.end); - var hiddenDurationBefore = DateUtil.getHiddenDurationBefore(this.body.hiddenDates, this, centerDate); - var hiddenDurationAfter = hiddenDuration - hiddenDurationBefore; - - // calculate new start and end - var newStart = (centerDate - hiddenDurationBefore) + (this.props.touch.start - (centerDate - hiddenDurationBefore)) * scale; - var newEnd = (centerDate + hiddenDurationAfter) + (this.props.touch.end - (centerDate + hiddenDurationAfter)) * scale; + // only react on left mouse button down + this.leftButtonDown = event.which ? (event.which === 1) : (event.button === 1); + if (!this.leftButtonDown && !this.touchDown) return; - // snapping times away from hidden zones - this.startToFront = 1 - scale > 0 ? false : true; // used to do the right autocorrection with periodic hidden times - this.endToFront = scale - 1 > 0 ? false : true; // used to do the right autocorrection with periodic hidden times + // get mouse position (different code for IE and all other browsers) + this.startMouseX = getMouseX(event); + this.startMouseY = getMouseY(event); - var safeStart = DateUtil.snapAwayFromHidden(this.body.hiddenDates, newStart, 1 - scale, true); - var safeEnd = DateUtil.snapAwayFromHidden(this.body.hiddenDates, newEnd, scale - 1, true); - if (safeStart != newStart || safeEnd != newEnd) { - this.props.touch.start = safeStart; - this.props.touch.end = safeEnd; - this.scaleOffset = 1 - event.gesture.scale; - newStart = safeStart; - newEnd = safeEnd; - } + this.startStart = new Date(this.start); + this.startEnd = new Date(this.end); + this.startArmRotation = this.camera.getArmRotation(); - this.setRange(newStart, newEnd, false, true); + this.frame.style.cursor = 'move'; - this.startToFront = false; // revert to default - this.endToFront = true; // revert to default - } + // 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); }; + /** - * Helper function to calculate the center date for zooming - * @param {{x: Number, y: Number}} pointer - * @return {number} date - * @private + * Perform moving operating. + * This function activated from within the funcion Graph.mouseDown(). + * @param {Event} event Well, eehh, the event */ - Range.prototype._pointerToDate = function (pointer) { - var conversion; - var direction = this.options.direction; + Graph3d.prototype._onMouseMove = function (event) { + event = event || window.event; - validateDirection(direction); + // calculate change in mouse position + var diffX = parseFloat(getMouseX(event)) - this.startMouseX; + var diffY = parseFloat(getMouseY(event)) - this.startMouseY; - if (direction == 'horizontal') { - return this.body.util.toTime(pointer.x).valueOf(); + 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; } - else { - var height = this.body.domProps.center.height; - conversion = this.conversion(height); - return pointer.y / conversion.scale + conversion.offset; + 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; + } + if (Math.abs(Math.cos(verticalNew)) < snapValue) { + verticalNew = (Math.round((verticalNew/ Math.PI - 0.5)) + 0.5) * Math.PI; } + + this.camera.setArmRotation(horizontalNew, verticalNew); + this.redraw(); + + // fire a cameraPositionChange event + var parameters = this.getCameraPosition(); + this.emit('cameraPositionChange', parameters); + + util.preventDefault(event); }; + /** - * 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 + * Stop moving operating. + * This function activated from within the funcion Graph.mouseDown(). + * @param {event} event The event */ - function getPointer (touch, element) { - return { - x: touch.pageX - util.getAbsoluteLeft(element), - y: touch.pageY - util.getAbsoluteTop(element) - }; - } + Graph3d.prototype._onMouseUp = function (event) { + this.frame.style.cursor = 'auto'; + this.leftButtonDown = false; + + // remove event listeners here + util.removeEventListener(document, 'mousemove', this.onmousemove); + util.removeEventListener(document, 'mouseup', this.onmouseup); + util.preventDefault(event); + }; /** - * 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. + * 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 */ - Range.prototype.zoom = function(scale, center, delta) { - // if centerDate is not provided, take it half between start Date and end Date - if (center == null) { - center = (this.start + this.end) / 2; - } + Graph3d.prototype._onTooltip = function (event) { + var delay = 300; // ms + var boundingRect = this.frame.getBoundingClientRect(); + var mouseX = getMouseX(event) - boundingRect.left; + var mouseY = getMouseY(event) - boundingRect.top; - var hiddenDuration = DateUtil.getHiddenDurationBetween(this.body.hiddenDates, this.start, this.end); - var hiddenDurationBefore = DateUtil.getHiddenDurationBefore(this.body.hiddenDates, this, center); - var hiddenDurationAfter = hiddenDuration - hiddenDurationBefore; + if (!this.showTooltip) { + return; + } - // calculate new start and end - var newStart = (center-hiddenDurationBefore) + (this.start - (center-hiddenDurationBefore)) * scale; - var newEnd = (center+hiddenDurationAfter) + (this.end - (center+hiddenDurationAfter)) * scale; + if (this.tooltipTimeout) { + clearTimeout(this.tooltipTimeout); + } - // snapping times away from hidden zones - this.startToFront = delta > 0 ? false : true; // used to do the right autocorrection with periodic hidden times - this.endToFront = -delta > 0 ? false : true; // used to do the right autocorrection with periodic hidden times - var safeStart = DateUtil.snapAwayFromHidden(this.body.hiddenDates, newStart, delta, true); - var safeEnd = DateUtil.snapAwayFromHidden(this.body.hiddenDates, newEnd, -delta, true); - if (safeStart != newStart || safeEnd != newEnd) { - newStart = safeStart; - newEnd = safeEnd; + // (delayed) display of a tooltip only if no mouse button is down + if (this.leftButtonDown) { + this._hideTooltip(); + return; } - this.setRange(newStart, newEnd, false, true); + 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 { + // tooltip is currently not visible + var me = this; + this.tooltipTimeout = setTimeout(function () { + me.tooltipTimeout = null; - this.startToFront = false; // revert to default - this.endToFront = true; // revert to default + // show a tooltip if we have a data point + var dataPoint = me._dataPointFromXY(mouseX, mouseY); + if (dataPoint) { + me._showTooltip(dataPoint); + } + }, delay); + } }; - - /** - * 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 + * Event handler for touchstart event on mobile devices */ - 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; + Graph3d.prototype._onTouchStart = function(event) { + this.touchDown = true; - // TODO: reckon with min and max range + 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.start = newStart; - this.end = newEnd; + this._onMouseDown(event); }; /** - * Move the range to a new center point - * @param {Number} moveTo New center point of the range + * Event handler for touchmove event on mobile devices */ - Range.prototype.moveTo = function(moveTo) { - var center = (this.start + this.end) / 2; + Graph3d.prototype._onTouchMove = function(event) { + this._onMouseMove(event); + }; - var diff = center - moveTo; + /** + * Event handler for touchend event on mobile devices + */ + Graph3d.prototype._onTouchEnd = function(event) { + this.touchDown = false; - // calculate new start and end - var newStart = this.start - diff; - var newEnd = this.end - diff; + util.removeEventListener(document, 'touchmove', this.ontouchmove); + util.removeEventListener(document, 'touchend', this.ontouchend); - this.setRange(newStart, newEnd); + this._onMouseUp(event); }; - module.exports = Range; + /** + * Event handler for mouse wheel event, used to zoom the graph + * Code from http://adomas.org/javascript-mouse-wheel/ + * @param {event} event The event + */ + Graph3d.prototype._onWheel = function(event) { + if (!event) /* For IE. */ + event = window.event; -/***/ }, -/* 18 */ -/***/ function(module, exports, __webpack_require__) { + // 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; + } - // Utility functions for ordering and stacking of items - var EPSILON = 0.001; // used when checking collisions, to prevent round-off errors + // 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); - /** - * Order items by their start data - * @param {Item[]} items - */ - exports.orderByStart = function(items) { - items.sort(function (a, b) { - return a.data.start - b.data.start; - }); - }; + this.camera.setArmLength(newLength); + this.redraw(); - /** - * Order items by their end date. If they have no end date, their start date - * is used. - * @param {Item[]} items - */ - exports.orderByEnd = function(items) { - items.sort(function (a, b) { - var aTime = ('end' in a.data) ? a.data.end : a.data.start, - bTime = ('end' in b.data) ? b.data.end : b.data.start; + this._hideTooltip(); + } - return aTime - bTime; - }); + // fire a cameraPositionChange event + var parameters = this.getCameraPosition(); + this.emit('cameraPositionChange', parameters); + + // Prevent default actions caused by mouse wheel. + // That might be ugly, but we handle scrolls somehow + // anyway, so don't bother here.. + util.preventDefault(event); }; /** - * 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 + * 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 */ - exports.stack = function(items, margin, force) { - var i, iMax; + Graph3d.prototype._insideTriangle = function (point, triangle) { + var a = triangle[0], + b = triangle[1], + c = triangle[2]; - if (force) { - // reset top position of all items - for (i = 0, iMax = items.length; i < iMax; i++) { - items[i].top = null; - } + function sign (x) { + return x > 0 ? 1 : x < 0 ? -1 : 0; } - // calculate new, non-overlapping positions - for (i = 0, iMax = items.length; i < iMax; i++) { - var item = items[i]; - if (item.stack && item.top === null) { - // initialize top position - item.top = margin.axis; - - do { - // TODO: optimize checking for overlap. when there is a gap without items, - // you only need to check for items from the next item on, not from zero - var collidingItem = null; - for (var j = 0, jj = items.length; j < jj; j++) { - var other = items[j]; - if (other.top !== null && other !== item && other.stack && exports.collision(item, other, margin.item)) { - collidingItem = other; - break; - } - } + 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)); - 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); - } - } + // 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); }; - /** - * 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. + * 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 */ - exports.nostack = function(items, margin, subgroups) { - var i, iMax, newTop; + Graph3d.prototype._dataPointFromXY = function (x, y) { + var i, + distMax = 100, // px + dataPoint = null, + closestDataPoint = null, + closestDist = null, + center = new Point2d(x, y); - // reset top position of all items - for (i = 0, iMax = items.length; i < iMax; i++) { - if (items[i].data.subgroup !== undefined) { - newTop = margin.axis; - for (var subgroup in subgroups) { - if (subgroups.hasOwnProperty(subgroup)) { - if (subgroups[subgroup].visible == true && subgroups[subgroup].index < subgroups[items[i].data.subgroup].index) { - newTop += subgroups[subgroup].height + margin.item.vertical; + 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; } } } - items[i].top = newTop; - } - else { - items[i].top = margin.axis; } } - }; - - /** - * Test if the two provided items collide - * The items must have parameters left, width, top, and height. - * @param {Item} a The first item - * @param {Item} b The second item - * @param {{horizontal: number, vertical: number}} margin - * An object containing a horizontal and vertical - * minimum required margin. - * @return {boolean} true if a and b collide, else false - */ - exports.collision = function(a, b, margin) { - return ((a.left - margin.horizontal + EPSILON) < (b.left + b.width) && - (a.left + a.width + margin.horizontal - EPSILON) > b.left && - (a.top - margin.vertical + EPSILON) < (b.top + b.height) && - (a.top + a.height + margin.vertical - EPSILON) > b.top); - }; + 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; + } + } + } + } -/***/ }, -/* 19 */ -/***/ function(module, exports, __webpack_require__) { - var moment = __webpack_require__(44); - var DateUtil = __webpack_require__(15); - var util = __webpack_require__(1); + return closestDataPoint; + }; /** - * @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 + * Display a tooltip for given data point + * @param {Object} dataPoint + * @private */ - function TimeStep(start, end, minimumStep, hiddenDates) { - // variables - this.current = new Date(); - this._start = new Date(); - this._end = new Date(); + Graph3d.prototype._showTooltip = function (dataPoint) { + var content, line, dot; - this.autoScale = true; - this.scale = 'day'; - this.step = 1; + 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)'; - // initialize the range - this.setRange(start, end, minimumStep); + line = document.createElement('div'); + line.style.position = 'absolute'; + line.style.height = '40px'; + line.style.width = '0'; + line.style.borderLeft = '1px solid #4d4d4d'; - // hidden Dates options - this.switchedDay = false; - this.switchedMonth = false; - this.switchedYear = false; - this.hiddenDates = hiddenDates; - if (hiddenDates === undefined) { - this.hiddenDates = []; + 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 + } + }; + } + else { + content = this.tooltip.dom.content; + line = this.tooltip.dom.line; + dot = this.tooltip.dom.dot; } - this.format = TimeStep.FORMAT; // default formatting - } + this._hideTooltip(); - // Time formatting - TimeStep.FORMAT = { - minorLabels: { - millisecond:'SSS', - second: 's', - minute: 'HH:mm', - hour: 'HH:mm', - weekday: 'ddd D', - day: 'D', - month: 'MMM', - year: 'YYYY' - }, - majorLabels: { - millisecond:'HH:mm:ss', - second: 'D MMMM HH:mm', - minute: 'ddd D MMMM', - hour: 'ddd D MMMM', - weekday: 'MMMM YYYY', - day: 'MMMM YYYY', - month: 'YYYY', - year: '' + this.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 + '
'; } + + 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'; }; /** - * Set custom formatting for the minor an major labels of the TimeStep. - * Both `minorLabels` and `majorLabels` are an Object with properties: - * 'millisecond, 'second, 'minute', 'hour', 'weekday, 'day, 'month, 'year'. - * @param {{minorLabels: Object, majorLabels: Object}} format + * Hide the tooltip when displayed + * @private */ - TimeStep.prototype.setFormat = function (format) { - var defaultFormat = util.deepExtend({}, TimeStep.FORMAT); - this.format = util.deepExtend(defaultFormat, format); + 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); + } + } + } + } }; + /**--------------------------------------------------------------------------**/ + + /** - * 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 + * Get the horizontal mouse position from a mouse event + * @param {Event} event + * @return {Number} mouse x */ - TimeStep.prototype.setRange = function(start, end, minimumStep) { - if (!(start instanceof Date) || !(end instanceof Date)) { - throw "No legal start or end date in method setRange"; - } + function getMouseX (event) { + if ('clientX' in event) return event.clientX; + return event.targetTouches[0] && event.targetTouches[0].clientX || 0; + } - this._start = (start != undefined) ? new Date(start.valueOf()) : new Date(); - this._end = (end != undefined) ? new Date(end.valueOf()) : new Date(); + /** + * Get the vertical mouse position from a mouse event + * @param {Event} event + * @return {Number} mouse y + */ + function getMouseY (event) { + if ('clientY' in event) return event.clientY; + return event.targetTouches[0] && event.targetTouches[0].clientY || 0; + } - if (this.autoScale) { - this.setMinimumStep(minimumStep); - } - }; + module.exports = Graph3d; + + +/***/ }, +/* 11 */ +/***/ function(module, exports, __webpack_require__) { + /** - * Set the range iterator to the start date. + * Expose `Emitter`. */ - TimeStep.prototype.first = function() { - this.current = new Date(this._start.valueOf()); - this.roundToMinor(); + + module.exports = Emitter; + + /** + * Initialize a new `Emitter`. + * + * @api public + */ + + function Emitter(obj) { + if (obj) return mixin(obj); }; /** - * Round the current date to the first minor date value - * This must be executed once when the current date is set to start Date + * Mixin the emitter properties. + * + * @param {Object} obj + * @return {Object} + * @api private */ - TimeStep.prototype.roundToMinor = function() { - // round to floor - // IMPORTANT: we have no breaks in this switch! (this is no bug) - // noinspection FallThroughInSwitchStatementJS - switch (this.scale) { - case 'year': - this.current.setFullYear(this.step * Math.floor(this.current.getFullYear() / this.step)); - this.current.setMonth(0); - case 'month': this.current.setDate(1); - case 'day': // intentional fall through - case 'weekday': this.current.setHours(0); - case 'hour': this.current.setMinutes(0); - case 'minute': this.current.setSeconds(0); - case 'second': this.current.setMilliseconds(0); - //case 'millisecond': // nothing to do for milliseconds - } - if (this.step != 1) { - // round down to the first minor value that is a multiple of the current step size - switch (this.scale) { - case 'millisecond': this.current.setMilliseconds(this.current.getMilliseconds() - this.current.getMilliseconds() % this.step); break; - case 'second': this.current.setSeconds(this.current.getSeconds() - this.current.getSeconds() % this.step); break; - case 'minute': this.current.setMinutes(this.current.getMinutes() - this.current.getMinutes() % this.step); break; - case 'hour': this.current.setHours(this.current.getHours() - this.current.getHours() % this.step); break; - case 'weekday': // intentional fall through - case 'day': this.current.setDate((this.current.getDate()-1) - (this.current.getDate()-1) % this.step + 1); break; - case 'month': this.current.setMonth(this.current.getMonth() - this.current.getMonth() % this.step); break; - case 'year': this.current.setFullYear(this.current.getFullYear() - this.current.getFullYear() % this.step); break; - default: break; - } + function mixin(obj) { + for (var key in Emitter.prototype) { + obj[key] = Emitter.prototype[key]; } + return obj; + } + + /** + * Listen on the given `event` with `fn`. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + + Emitter.prototype.on = + Emitter.prototype.addEventListener = function(event, fn){ + this._callbacks = this._callbacks || {}; + (this._callbacks[event] = this._callbacks[event] || []) + .push(fn); + return this; }; /** - * Check if the there is a next step - * @return {boolean} true if the current date has not passed the end date + * Adds an `event` listener that will be invoked a single + * time then automatically removed. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public */ - TimeStep.prototype.hasNext = function () { - return (this.current.valueOf() <= this._end.valueOf()); + + Emitter.prototype.once = function(event, fn){ + var self = this; + this._callbacks = this._callbacks || {}; + + function on() { + self.off(event, on); + fn.apply(this, arguments); + } + + on.fn = fn; + this.on(event, on); + return this; }; /** - * Do the next step + * Remove the given callback for `event` or all + * registered callbacks. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public */ - TimeStep.prototype.next = function() { - var prev = this.current.valueOf(); - // Two cases, needed to prevent issues with switching daylight savings - // (end of March and end of October) - if (this.current.getMonth() < 6) { - switch (this.scale) { - case 'millisecond': + Emitter.prototype.off = + Emitter.prototype.removeListener = + Emitter.prototype.removeAllListeners = + Emitter.prototype.removeEventListener = function(event, fn){ + this._callbacks = this._callbacks || {}; - this.current = new Date(this.current.valueOf() + this.step); break; - case 'second': this.current = new Date(this.current.valueOf() + this.step * 1000); break; - case 'minute': this.current = new Date(this.current.valueOf() + this.step * 1000 * 60); break; - case '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 'weekday': // intentional fall through - case 'day': this.current.setDate(this.current.getDate() + this.step); break; - case 'month': this.current.setMonth(this.current.getMonth() + this.step); break; - case 'year': this.current.setFullYear(this.current.getFullYear() + this.step); break; - default: break; - } + // all + if (0 == arguments.length) { + this._callbacks = {}; + return this; } - else { - switch (this.scale) { - case 'millisecond': this.current = new Date(this.current.valueOf() + this.step); break; - case 'second': this.current.setSeconds(this.current.getSeconds() + this.step); break; - case 'minute': this.current.setMinutes(this.current.getMinutes() + this.step); break; - case 'hour': this.current.setHours(this.current.getHours() + this.step); break; - case 'weekday': // intentional fall through - case 'day': this.current.setDate(this.current.getDate() + this.step); break; - case 'month': this.current.setMonth(this.current.getMonth() + this.step); break; - case 'year': this.current.setFullYear(this.current.getFullYear() + this.step); break; - default: break; - } + + // specific event + var callbacks = this._callbacks[event]; + if (!callbacks) return this; + + // remove all handlers + if (1 == arguments.length) { + delete this._callbacks[event]; + return this; } - if (this.step != 1) { - // round down to the correct major value - switch (this.scale) { - case 'millisecond': if(this.current.getMilliseconds() < this.step) this.current.setMilliseconds(0); break; - case 'second': if(this.current.getSeconds() < this.step) this.current.setSeconds(0); break; - case 'minute': if(this.current.getMinutes() < this.step) this.current.setMinutes(0); break; - case 'hour': if(this.current.getHours() < this.step) this.current.setHours(0); break; - case 'weekday': // intentional fall through - case 'day': if(this.current.getDate() < this.step+1) this.current.setDate(1); break; - case 'month': if(this.current.getMonth() < this.step) this.current.setMonth(0); break; - case 'year': break; // nothing to do for year - default: break; + // 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; + }; - // safety mechanism: if current time is still unchanged, move to the end - if (this.current.valueOf() == prev) { - this.current = new Date(this._end.valueOf()); + /** + * Emit `event` with the given args. + * + * @param {String} event + * @param {Mixed} ... + * @return {Emitter} + */ + + Emitter.prototype.emit = function(event){ + this._callbacks = this._callbacks || {}; + var args = [].slice.call(arguments, 1) + , callbacks = this._callbacks[event]; + + if (callbacks) { + callbacks = callbacks.slice(0); + for (var i = 0, len = callbacks.length; i < len; ++i) { + callbacks[i].apply(this, args); + } } - DateUtil.stepOverHiddenDates(this, prev); + return this; }; - /** - * Get the current datetime - * @return {Date} current The current date + * Return array of callbacks for `event`. + * + * @param {String} event + * @return {Array} + * @api public */ - TimeStep.prototype.getCurrent = function() { - return this.current; + + Emitter.prototype.listeners = function(event){ + this._callbacks = this._callbacks || {}; + return this._callbacks[event] || []; }; /** - * Set a custom scale. Autoscaling will be disabled. - * For example setScale('minute', 5) will result - * in minor steps of 5 minutes, and major steps of an hour. + * Check if this emitter has `event` handlers. * - * @param {{scale: string, step: number}} params - * An object containing two properties: - * - A string 'scale'. Choose from 'millisecond', 'second', - * 'minute', 'hour', 'weekday, 'day, 'month, 'year'. - * - A number 'step'. A step size, by default 1. - * Choose for example 1, 2, 5, or 10. + * @param {String} event + * @return {Boolean} + * @api public */ - TimeStep.prototype.setScale = function(params) { - if (params && typeof params.scale == 'string') { - this.scale = params.scale; - this.step = params.step > 0 ? params.step : 1; - this.autoScale = false; - } + + Emitter.prototype.hasListeners = function(event){ + return !! this.listeners(event).length; + }; + + +/***/ }, +/* 12 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * @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; }; /** - * Enable or disable autoscaling - * @param {boolean} enable If true, autoascaling is set true + * Subtract the two provided points, returns a-b + * @param {Point3d} a + * @param {Point3d} b + * @return {Point3d} a-b */ - TimeStep.prototype.setAutoScale = function (enable) { - this.autoScale = enable; + 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; }; + /** + * 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; + }; /** - * Automatically determine the scale that bests fits the provided minimum step - * @param {Number} [minimumStep] The minimum step size in milliseconds + * Calculate the average of two 3d points + * @param {Point3d} a + * @param {Point3d} b + * @return {Point3d} The average, (a+b)/2 */ - TimeStep.prototype.setMinimumStep = function(minimumStep) { - if (minimumStep == undefined) { - return; - } + Point3d.avg = function(a, b) { + return new Point3d( + (a.x + b.x) / 2, + (a.y + b.y) / 2, + (a.z + b.z) / 2 + ); + }; - //var b = asc + ds; + /** + * 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 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); + 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; - // find the smallest step that is larger than the provided minimumStep - if (stepYear*1000 > minimumStep) {this.scale = 'year'; this.step = 1000;} - if (stepYear*500 > minimumStep) {this.scale = 'year'; this.step = 500;} - if (stepYear*100 > minimumStep) {this.scale = 'year'; this.step = 100;} - if (stepYear*50 > minimumStep) {this.scale = 'year'; this.step = 50;} - if (stepYear*10 > minimumStep) {this.scale = 'year'; this.step = 10;} - if (stepYear*5 > minimumStep) {this.scale = 'year'; this.step = 5;} - if (stepYear > minimumStep) {this.scale = 'year'; this.step = 1;} - if (stepMonth*3 > minimumStep) {this.scale = 'month'; this.step = 3;} - if (stepMonth > minimumStep) {this.scale = 'month'; this.step = 1;} - if (stepDay*5 > minimumStep) {this.scale = 'day'; this.step = 5;} - if (stepDay*2 > minimumStep) {this.scale = 'day'; this.step = 2;} - if (stepDay > minimumStep) {this.scale = 'day'; this.step = 1;} - if (stepDay/2 > minimumStep) {this.scale = 'weekday'; this.step = 1;} - if (stepHour*4 > minimumStep) {this.scale = 'hour'; this.step = 4;} - if (stepHour > minimumStep) {this.scale = 'hour'; this.step = 1;} - if (stepMinute*15 > minimumStep) {this.scale = 'minute'; this.step = 15;} - if (stepMinute*10 > minimumStep) {this.scale = 'minute'; this.step = 10;} - if (stepMinute*5 > minimumStep) {this.scale = 'minute'; this.step = 5;} - if (stepMinute > minimumStep) {this.scale = 'minute'; this.step = 1;} - if (stepSecond*15 > minimumStep) {this.scale = 'second'; this.step = 15;} - if (stepSecond*10 > minimumStep) {this.scale = 'second'; this.step = 10;} - if (stepSecond*5 > minimumStep) {this.scale = 'second'; this.step = 5;} - if (stepSecond > minimumStep) {this.scale = 'second'; this.step = 1;} - if (stepMillisecond*200 > minimumStep) {this.scale = 'millisecond'; this.step = 200;} - if (stepMillisecond*100 > minimumStep) {this.scale = 'millisecond'; this.step = 100;} - if (stepMillisecond*50 > minimumStep) {this.scale = 'millisecond'; this.step = 50;} - if (stepMillisecond*10 > minimumStep) {this.scale = 'millisecond'; this.step = 10;} - if (stepMillisecond*5 > minimumStep) {this.scale = 'millisecond'; this.step = 5;} - if (stepMillisecond > minimumStep) {this.scale = 'millisecond'; this.step = 1;} + return crossproduct; }; + /** - * Snap a date to a rounded value. - * The snap intervals are dependent on the current scale and step. - * Static function - * @param {Date} date the date to be snapped. - * @param {string} scale Current scale, can be 'millisecond', 'second', - * 'minute', 'hour', 'weekday, 'day, 'month, 'year'. - * @param {number} step Current step (1, 2, 4, 5, ... - * @return {Date} snappedDate + * Rtrieve the length of the vector (or the distance from this point to the origin + * @return {Number} length */ - TimeStep.snap = function(date, scale, step) { - var clone = new Date(date.valueOf()); - - if (scale == 'year') { - var year = clone.getFullYear() + Math.round(clone.getMonth() / 12); - clone.setFullYear(Math.round(year / step) * step); - clone.setMonth(0); - clone.setDate(0); - clone.setHours(0); - clone.setMinutes(0); - clone.setSeconds(0); - clone.setMilliseconds(0); - } - else if (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); - } - - clone.setHours(0); - clone.setMinutes(0); - clone.setSeconds(0); - clone.setMilliseconds(0); - } - else if (scale == 'day') { - //noinspection FallthroughInSwitchStatementJS - switch (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 (scale == 'weekday') { - //noinspection FallthroughInSwitchStatementJS - switch (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 (scale == 'hour') { - switch (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 (scale == 'minute') { - //noinspection FallthroughInSwitchStatementJS - switch (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 (scale == 'second') { - //noinspection FallthroughInSwitchStatementJS - switch (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 (scale == 'millisecond') { - var _step = step > 5 ? step / 2 : 1; - clone.setMilliseconds(Math.round(clone.getMilliseconds() / _step) * _step); - } - - return clone; + Point3d.prototype.length = function() { + return Math.sqrt( + this.x * this.x + + this.y * this.y + + this.z * this.z + ); }; - /** - * Check if the current value is a major value (for example when the step - * is DAY, a major value is each first day of the MONTH) - * @return {boolean} true if current date is major, else false. - */ - TimeStep.prototype.isMajor = function() { - if (this.switchedYear == true) { - this.switchedYear = false; - switch (this.scale) { - case 'year': - case 'month': - case 'weekday': - case 'day': - case 'hour': - case 'minute': - case 'second': - case 'millisecond': - return true; - default: - return false; - } - } - else if (this.switchedMonth == true) { - this.switchedMonth = false; - switch (this.scale) { - case 'weekday': - case 'day': - case 'hour': - case 'minute': - case 'second': - case 'millisecond': - return true; - default: - return false; - } - } - else if (this.switchedDay == true) { - this.switchedDay = false; - switch (this.scale) { - case 'millisecond': - case 'second': - case 'minute': - case 'hour': - return true; - default: - return false; - } - } + module.exports = Point3d; - switch (this.scale) { - case 'millisecond': - return (this.current.getMilliseconds() == 0); - case 'second': - return (this.current.getSeconds() == 0); - case 'minute': - return (this.current.getHours() == 0) && (this.current.getMinutes() == 0); - case 'hour': - return (this.current.getHours() == 0); - case 'weekday': // intentional fall through - case 'day': - return (this.current.getDate() == 1); - case 'month': - return (this.current.getMonth() == 0); - case 'year': - return false; - default: - return false; - } - }; +/***/ }, +/* 13 */ +/***/ function(module, exports, __webpack_require__) { /** - * 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 + * @prototype Point2d + * @param {Number} [x] + * @param {Number} [y] */ - TimeStep.prototype.getLabelMinor = function(date) { - if (date == undefined) { - date = this.current; - } + function Point2d (x, y) { + this.x = x !== undefined ? x : 0; + this.y = y !== undefined ? y : 0; + } - var format = this.format.minorLabels[this.scale]; - return (format && format.length > 0) ? moment(date).format(format) : ''; - }; + module.exports = Point2d; + + +/***/ }, +/* 14 */ +/***/ function(module, exports, __webpack_require__) { + + var Point3d = __webpack_require__(12); /** - * 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 + * @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 */ - TimeStep.prototype.getLabelMajor = function(date) { - if (date == undefined) { - date = this.current; - } + function Camera() { + this.armLocation = new Point3d(); + this.armRotation = {}; + this.armRotation.horizontal = 0; + this.armRotation.vertical = 0; + this.armLength = 1.7; - var format = this.format.majorLabels[this.scale]; - return (format && format.length > 0) ? moment(date).format(format) : ''; - }; + this.cameraLocation = new Point3d(); + this.cameraRotation = new Point3d(0.5*Math.PI, 0, 0); - TimeStep.prototype.getClassName = function() { - var m = moment(this.current); - var date = m.locale ? m.locale('en') : m.lang('en'); // old versions of moment have .lang() function - var step = this.step; + this.calculateCameraOrientation(); + } - function even(value) { - return (value / step % 2 == 0) ? ' even' : ' odd'; - } + /** + * 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 + */ + Camera.prototype.setArmLocation = function(x, y, z) { + this.armLocation.x = x; + this.armLocation.y = y; + this.armLocation.z = z; - function today(date) { - if (date.isSame(new Date(), 'day')) { - return ' today'; - } - if (date.isSame(moment().add(1, 'day'), 'day')) { - return ' tomorrow'; - } - if (date.isSame(moment().add(-1, 'day'), 'day')) { - return ' yesterday'; - } - return ''; - } + this.calculateCameraOrientation(); + }; - function currentWeek(date) { - return date.isSame(new Date(), 'week') ? ' current-week' : ''; + /** + * 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; } - function currentMonth(date) { - return date.isSame(new Date(), 'month') ? ' current-month' : ''; + 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; } - function currentYear(date) { - return date.isSame(new Date(), 'year') ? ' current-year' : ''; + if (horizontal !== undefined || vertical !== undefined) { + this.calculateCameraOrientation(); } + }; - switch (this.scale) { - case 'millisecond': - return even(date.milliseconds()).trim(); - - case 'second': - return even(date.seconds()).trim(); - - case 'minute': - return even(date.minutes()).trim(); - - case 'hour': - var hours = date.hours(); - if (this.step == 4) { - hours = hours + '-' + (hours + 4); - } - return hours + 'h' + today(date) + even(date.hours()); - - case 'weekday': - return date.format('dddd').toLowerCase() + - today(date) + currentWeek(date) + even(date.date()); - - case 'day': - var day = date.date(); - var month = date.format('MMMM').toLowerCase(); - return 'day' + day + ' ' + month + currentMonth(date) + even(day - 1); - - case 'month': - return date.format('MMMM').toLowerCase() + - currentMonth(date) + even(date.month()); - - case 'year': - var year = date.year(); - return 'year' + year + currentYear(date)+ even(year); + /** + * Retrieve the current arm rotation + * @return {object} An object with parameters horizontal and vertical + */ + Camera.prototype.getArmRotation = function() { + var rot = {}; + rot.horizontal = this.armRotation.horizontal; + rot.vertical = this.armRotation.vertical; - default: - return ''; - } + return rot; }; - module.exports = TimeStep; + /** + * Set the (normalized) length of the camera arm. + * @param {Number} length A length between 0.71 and 5.0 + */ + Camera.prototype.setArmLength = function(length) { + if (length === undefined) + return; + this.armLength = length; -/***/ }, -/* 20 */ -/***/ function(module, exports, __webpack_require__) { + // 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; - /** - * 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; - } + this.calculateCameraOrientation(); + }; /** - * Set options for the component. The new options will be merged into the - * current options. - * @param {Object} options + * Retrieve the arm length + * @return {Number} length */ - Component.prototype.setOptions = function(options) { - if (options) { - util.extend(this.options, options); - } + Camera.prototype.getArmLength = function() { + return this.armLength; }; /** - * Repaint the component - * @return {boolean} Returns true if the component is resized + * Retrieve the camera location + * @return {Point3d} cameraLocation */ - Component.prototype.redraw = function() { - // should be implemented by the component - return false; + Camera.prototype.getCameraLocation = function() { + return this.cameraLocation; }; /** - * Destroy the component. Cleanup DOM and event listeners + * Retrieve the camera rotation + * @return {Point3d} cameraRotation */ - Component.prototype.destroy = function() { - // should be implemented by the component + Camera.prototype.getCameraRotation = function() { + return this.cameraRotation; }; /** - * Test whether the component is resized since the last time _isResized() was - * called. - * @return {Boolean} Returns true if the component is resized - * @protected + * Calculate the location and rotation of the camera based on the + * position and orientation of the camera arm */ - 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; + 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); - return resized; + // 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 = Component; - + module.exports = Camera; /***/ }, -/* 21 */ +/* 15 */ /***/ function(module, exports, __webpack_require__) { - var util = __webpack_require__(1); - var Component = __webpack_require__(20); - var moment = __webpack_require__(44); - var locales = __webpack_require__(48); + var DataView = __webpack_require__(9); /** - * A current time bar - * @param {{range: Range, dom: Object, domProps: Object}} body - * @param {Object} [options] Available parameters: - * {Boolean} [showCurrentTime] - * @constructor CurrentTime - * @extends Component + * @class Filter + * + * @param {DataSet} data The google data table + * @param {Number} column The index of the column to be filtered + * @param {Graph} graph The graph */ - function CurrentTime (body, options) { - this.body = body; + function Filter (data, column, graph) { + this.data = data; + this.column = column; + this.graph = graph; // the parent graph - // default options - this.defaultOptions = { - showCurrentTime: true, + this.index = undefined; + this.value = undefined; - locales: locales, - locale: 'en' - }; - this.options = util.extend({}, this.defaultOptions); - this.offset = 0; + // read all distinct values and select the first one + this.values = graph.getDistinctValues(data.get(), this.column); - this._create(); + // sort both numeric and string values correctly + this.values.sort(function (a, b) { + return a > b ? 1 : a < b ? -1 : 0; + }); - this.setOptions(options); - } + if (this.values.length > 0) { + this.selectValue(0); + } + + // create an array with the filtered datapoints. this will be loaded afterwards + this.dataPoints = []; + + this.loaded = false; + this.onLoadCallback = undefined; + + if (graph.animationPreload) { + this.loaded = false; + this.loadInBackground(); + } + else { + this.loaded = true; + } + }; - CurrentTime.prototype = new Component(); /** - * Create the HTML DOM for the current time bar - * @private + * Return the label + * @return {string} label */ - 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; + Filter.prototype.isLoaded = function() { + return this.loaded; }; + /** - * Destroy the CurrentTime bar + * Return the loaded progress + * @return {Number} percentage between 0 and 100 */ - CurrentTime.prototype.destroy = function () { - this.options.showCurrentTime = false; - this.redraw(); // will remove the bar from the DOM and stop refreshing + Filter.prototype.getLoadedProgress = function() { + var len = this.values.length; - this.body = null; + var i = 0; + while (this.dataPoints[i]) { + i++; + } + + return Math.round(i / len * 100); }; + /** - * Set options for the component. Options will be merged in current options. - * @param {Object} options Available parameters: - * {boolean} [showCurrentTime] + * Return the label + * @return {string} label */ - CurrentTime.prototype.setOptions = function(options) { - if (options) { - // copy all options that we know - util.selectiveExtend(['showCurrentTime', 'locale', 'locales'], this.options, options); - } + Filter.prototype.getLabel = function() { + return this.graph.filterLabel; }; + /** - * Repaint the component - * @return {boolean} Returns true if the component is resized + * Return the columnIndex of the filter + * @return {Number} columnIndex */ - 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); + Filter.prototype.getColumn = function() { + return this.column; + }; - this.start(); - } + /** + * Return the currently selected value. Returns undefined if there is no selection + * @return {*} value + */ + Filter.prototype.getSelectedValue = function() { + if (this.index === undefined) + return undefined; - var now = new Date(new Date().valueOf() + this.offset); - var x = this.body.util.toScreen(now); + return this.values[this.index]; + }; - var locale = this.options.locales[this.options.locale]; - var title = locale.current + ' ' + locale.time + ': ' + moment(now).format('dddd, MMMM Do YYYY, H:mm:ss'); - title = title.charAt(0).toUpperCase() + title.substring(1); + /** + * Retrieve all values of the filter + * @return {Array} values + */ + Filter.prototype.getValues = function() { + return this.values; + }; - this.bar.style.left = x + 'px'; - this.bar.title = title; - } - else { - // remove the line from the DOM - if (this.bar.parentNode) { - this.bar.parentNode.removeChild(this.bar); - } - this.stop(); - } + /** + * 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 false; + return this.values[index]; }; + /** - * Start auto refreshing the current time bar + * Retrieve the (filtered) dataPoints for the currently selected filter index + * @param {Number} [index] (optional) + * @return {Array} dataPoints */ - CurrentTime.prototype.start = function() { - var me = this; + Filter.prototype._getDataPoints = function(index) { + if (index === undefined) + index = this.index; - function update () { - me.stop(); + if (index === undefined) + return []; - // 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; + var dataPoints; + if (this.dataPoints[index]) { + dataPoints = this.dataPoints[index]; + } + else { + var f = {}; + f.column = this.column; + f.value = this.values[index]; - me.redraw(); + var dataView = new DataView(this.data,{filter: function (item) {return (item[f.column] == f.value);}}).get(); + dataPoints = this.graph._getDataPoints(dataView); - // start a timer to adjust for the new time - me.currentTimeTimer = setTimeout(update, interval); + this.dataPoints[index] = dataPoints; } - update(); + return dataPoints; }; + + /** - * Stop auto refreshing the current time bar + * Set a callback function when the filter is fully loaded. */ - CurrentTime.prototype.stop = function() { - if (this.currentTimeTimer !== undefined) { - clearTimeout(this.currentTimeTimer); - delete this.currentTimeTimer; - } + Filter.prototype.setOnLoadCallback = function(callback) { + this.onLoadCallback = callback; }; + /** - * Set a current time. This can be used for example to ensure that a client's - * time is synchronized with a shared server time. - * @param {Date | String | Number} time A Date, unix timestamp, or - * ISO date string. + * Add a value to the list with available values for this filter + * No double entries will be created. + * @param {Number} index */ - CurrentTime.prototype.setCurrentTime = function(time) { - var t = util.convert(time, 'Date').valueOf(); - var now = new Date().valueOf(); - this.offset = t - now; - this.redraw(); + Filter.prototype.selectValue = function(index) { + if (index >= this.values.length) + throw 'Error: index out of range'; + + this.index = index; + this.value = this.values[index]; }; /** - * Get the current time. - * @return {Date} Returns the current time. + * Load all filtered rows in the background one by one + * Start this method without providing an index! */ - CurrentTime.prototype.getCurrentTime = function() { - return new Date(new Date().valueOf() + this.offset); + 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; + } + else { + this.loaded = true; + + // remove the progress box + if (frame.progress !== undefined) { + frame.removeChild(frame.progress); + frame.progress = undefined; + } + + if (this.onLoadCallback) + this.onLoadCallback(); + } }; - module.exports = CurrentTime; + module.exports = Filter; /***/ }, -/* 22 */ +/* 16 */ /***/ function(module, exports, __webpack_require__) { - var Hammer = __webpack_require__(45); var util = __webpack_require__(1); - var Component = __webpack_require__(20); - var moment = __webpack_require__(44); - var locales = __webpack_require__(48); /** - * A custom time bar - * @param {{range: Range, dom: Object}} body - * @param {Object} [options] Available parameters: - * {Boolean} [showCustomTime] - * @constructor CustomTime - * @extends Component + * @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; - function CustomTime (body, options) { - this.body = body; + 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); - // default options - this.defaultOptions = { - showCustomTime: false, - locales: locales, - locale: 'en' - }; - this.options = util.extend({}, this.defaultOptions); + this.frame.prev = document.createElement('INPUT'); + this.frame.prev.type = 'BUTTON'; + this.frame.prev.value = 'Prev'; + this.frame.appendChild(this.frame.prev); - this.customTime = new Date(); - this.eventParams = {}; // stores state parameters while dragging the bar + this.frame.play = document.createElement('INPUT'); + this.frame.play.type = 'BUTTON'; + this.frame.play.value = 'Play'; + this.frame.appendChild(this.frame.play); - // create the DOM - this._create(); + this.frame.next = document.createElement('INPUT'); + this.frame.next.type = 'BUTTON'; + this.frame.next.value = 'Next'; + this.frame.appendChild(this.frame.next); - this.setOptions(options); - } + 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); - CustomTime.prototype = new Component(); + 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);}; + } + + this.onChangeCallback = undefined; + + this.values = []; + this.index = undefined; + + this.playTimeout = undefined; + this.playInterval = 1000; // milliseconds + this.playLoop = true; + } /** - * Set options for the component. Options will be merged in current options. - * @param {Object} options Available parameters: - * {boolean} [showCustomTime] + * Select the previous index */ - CustomTime.prototype.setOptions = function(options) { - if (options) { - // copy all options that we know - util.selectiveExtend(['showCustomTime', 'locale', 'locales'], this.options, options); + Slider.prototype.prev = function() { + var index = this.getIndex(); + if (index > 0) { + index--; + this.setIndex(index); } }; /** - * Create the DOM for the custom time - * @private + * Select the next index */ - 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)); + Slider.prototype.next = function() { + var index = this.getIndex(); + if (index < this.values.length - 1) { + index++; + this.setIndex(index); + } }; /** - * Destroy the CustomTime bar + * Select the next index */ - CustomTime.prototype.destroy = function () { - this.options.showCustomTime = false; - this.redraw(); // will remove the bar from the DOM + Slider.prototype.playNext = function() { + var start = new Date(); - this.hammer.enable(false); - this.hammer = null; + 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.body = null; + 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); }; /** - * Repaint the component - * @return {boolean} Returns true if the component is resized + * Toggle start or stop playing */ - 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); - } + Slider.prototype.togglePlay = function() { + if (this.playTimeout === undefined) { + this.play(); + } else { + this.stop(); + } + }; - var x = this.body.util.toScreen(this.customTime); + /** + * Start playing + */ + Slider.prototype.play = function() { + // Test whether already playing + if (this.playTimeout) return; - var locale = this.options.locales[this.options.locale]; - var title = locale.time + ': ' + moment(this.customTime).format('dddd, MMMM Do YYYY, H:mm:ss'); - title = title.charAt(0).toUpperCase() + title.substring(1); + this.playNext(); - this.bar.style.left = x + 'px'; - this.bar.title = title; + if (this.frame) { + this.frame.play.value = 'Stop'; } - else { - // remove the line from the DOM - if (this.bar.parentNode) { - this.bar.parentNode.removeChild(this.bar); - } + }; + + /** + * Stop playing + */ + Slider.prototype.stop = function() { + clearInterval(this.playTimeout); + this.playTimeout = undefined; + + if (this.frame) { + this.frame.play.value = 'Play'; } + }; - return false; + /** + * Set a callback function which will be triggered when the value of the + * slider bar has changed. + */ + Slider.prototype.setOnChangeCallback = function(callback) { + this.onChangeCallback = callback; }; /** - * Set custom time. - * @param {Date | number | string} time + * Set the interval for playing the list + * @param {Number} interval The interval in milliseconds */ - CustomTime.prototype.setCustomTime = function(time) { - this.customTime = util.convert(time, 'Date'); - this.redraw(); + Slider.prototype.setPlayInterval = function(interval) { + this.playInterval = interval; }; /** - * Retrieve the current custom time. - * @return {Date} customTime + * Retrieve the current play interval + * @return {Number} interval The interval in milliseconds */ - CustomTime.prototype.getCustomTime = function() { - return new Date(this.customTime.valueOf()); + Slider.prototype.getPlayInterval = function(interval) { + return this.playInterval; }; /** - * Start moving horizontally - * @param {Event} event - * @private + * 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. */ - CustomTime.prototype._onDragStart = function(event) { - this.eventParams.dragging = true; - this.eventParams.customTime = this.customTime; + Slider.prototype.setPlayLoop = function(doLoop) { + this.playLoop = doLoop; + }; - event.stopPropagation(); - event.preventDefault(); + + /** + * Execute the onchange callback function + */ + Slider.prototype.onChange = function() { + if (this.onChangeCallback !== undefined) { + this.onChangeCallback(); + } }; /** - * Perform moving operating. - * @param {Event} event - * @private + * redraw the slider on the correct place */ - CustomTime.prototype._onDrag = function (event) { - if (!this.eventParams.dragging) return; + 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'; - var deltaX = event.gesture.deltaX, - x = this.body.util.toScreen(this.eventParams.customTime) + deltaX, - time = this.body.util.toTime(x); + // position the slider button + var left = this.indexToLeft(this.index); + this.frame.slide.style.left = (left) + 'px'; + } + }; - this.setCustomTime(time); - // fire a timechange event - this.body.emitter.emit('timechange', { - time: new Date(this.customTime.valueOf()) - }); + /** + * 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; - event.stopPropagation(); - event.preventDefault(); + if (this.values.length > 0) + this.setIndex(0); + else + this.index = undefined; }; /** - * Stop moving operating. - * @param {event} event - * @private + * Select a value by its index + * @param {Number} index */ - CustomTime.prototype._onDragEnd = function (event) { - if (!this.eventParams.dragging) return; - - // fire a timechanged event - this.body.emitter.emit('timechanged', { - time: new Date(this.customTime.valueOf()) - }); + Slider.prototype.setIndex = function(index) { + if (index < this.values.length) { + this.index = index; - event.stopPropagation(); - event.preventDefault(); + this.redraw(); + this.onChange(); + } + else { + throw 'Error: index out of range'; + } }; - module.exports = CustomTime; + /** + * retrieve the index of the currently selected vaue + * @return {Number} index + */ + Slider.prototype.getIndex = function() { + return this.index; + }; -/***/ }, -/* 23 */ -/***/ function(module, exports, __webpack_require__) { + /** + * retrieve the currently selected value + * @return {*} value + */ + Slider.prototype.get = function() { + return this.values[this.index]; + }; - var util = __webpack_require__(1); - var DOMutil = __webpack_require__(2); - var Component = __webpack_require__(20); - var DataStep = __webpack_require__(16); - /** - * A horizontal time axis - * @param {Object} [options] See DataAxis.setOptions for the available - * options. - * @constructor DataAxis - * @extends Component - * @param body - */ - function DataAxis (body, options, svg, linegraphOptions) { - this.id = util.randomUUID(); - 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; - 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, - alignZeros: true, - customRange: { - left: {min:undefined, max:undefined}, - right: {min:undefined, max:undefined} - }, - title: { - left: {text:undefined}, - right: {text:undefined} - }, - format: { - left: {decimals: undefined}, - right: {decimals: undefined} - } - }; + this.startClientX = event.clientX; + this.startSlideX = parseFloat(this.frame.slide.style.left); - this.linegraphOptions = linegraphOptions; - this.linegraphSVG = svg; - this.props = {}; - this.DOMelements = { // dynamic elements - lines: {}, - labels: {}, - title: {} - }; + this.frame.style.cursor = 'move'; - this.dom = {}; + // 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.range = {start:0, end:0}; - this.options = util.extend({}, this.defaultOptions); - this.conversionFactor = 1; + Slider.prototype.leftToIndex = function (left) { + var width = parseFloat(this.frame.bar.style.width) - + this.frame.slide.clientWidth - 10; + var x = left - 3; - this.setOptions(options); - this.width = Number(('' + this.options.width).replace("px","")); - this.minWidth = this.width; - this.height = this.linegraphSVG.offsetHeight; - this.hidden = false; + 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.stepPixels = 25; - this.stepPixelsForced = 25; - this.zeroCrossing = -1; + return index; + }; - this.lineOffset = 0; - this.master = true; - this.svgElements = {}; - this.iconsRemoved = false; + Slider.prototype.indexToLeft = function (index) { + var width = parseFloat(this.frame.bar.style.width) - + this.frame.slide.clientWidth - 10; + var x = index / (this.values.length-1) * width; + var left = x + 3; - this.groups = {}; - this.amountOfGroups = 0; + return left; + }; - // create the HTML DOM - this._create(); - var me = this; - this.body.emitter.on("verticalDrag", function() { - me.dom.lineContainer.style.top = me.body.domProps.scrollTop + 'px'; - }); - } - DataAxis.prototype = new Component(); + Slider.prototype._onMouseMove = function (event) { + var diff = event.clientX - this.startClientX; + var x = this.startSlideX + diff; + var index = this.leftToIndex(x); - DataAxis.prototype.addGroup = function(label, graphOptions) { - if (!this.groups.hasOwnProperty(label)) { - this.groups[label] = graphOptions; - } - this.amountOfGroups += 1; - }; + this.setIndex(index); - DataAxis.prototype.updateGroup = function(label, graphOptions) { - this.groups[label] = graphOptions; + util.preventDefault(); }; - DataAxis.prototype.removeGroup = function(label) { - if (this.groups.hasOwnProperty(label)) { - delete this.groups[label]; - this.amountOfGroups -= 1; - } + + Slider.prototype._onMouseUp = function (event) { + this.frame.style.cursor = 'auto'; + + // remove event listeners + util.removeEventListener(document, 'mousemove', this.onmousemove); + util.removeEventListener(document, 'mouseup', this.onmouseup); + + util.preventDefault(); }; + module.exports = Slider; - 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', - 'customRange', - 'title', - 'format', - 'alignZeros' - ]; - util.selectiveExtend(fields, this.options, options); - this.minWidth = Number(('' + this.options.width).replace("px","")); +/***/ }, +/* 17 */ +/***/ function(module, exports, __webpack_require__) { - if (redraw == true && this.dom.frame) { - this.hide(); - this.show(); - } - } + /** + * @prototype StepNumber + * The class StepNumber is an iterator for Numbers. You provide a start and end + * value, and a best step size. StepNumber itself rounds to fixed values and + * a finds the step that best fits the provided step. + * + * If prettyStep is true, the step size is chosen as close as possible to the + * provided step, but being a round value like 1, 2, 5, 10, 20, 50, .... + * + * Example usage: + * var step = new StepNumber(0, 10, 2.5, true); + * step.start(); + * while (!step.end()) { + * alert(step.getCurrent()); + * step.next(); + * } + * + * Version: 1.0 + * + * @param {Number} start The start value + * @param {Number} end The end value + * @param {Number} step Optional. Step size. Must be a positive value. + * @param {boolean} prettyStep Optional. If true, the step size is rounded + * To a pretty step size (like 1, 2, 5, 10, 20, 50, ...) + */ + function StepNumber(start, end, step, prettyStep) { + // set default values + this._start = 0; + this._end = 0; + this._step = 1; + this.prettyStep = true; + this.precision = 5; + + this._current = 0; + this.setRange(start, end, step, prettyStep); }; + /** + * 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; + + this.setStep(step, prettyStep); + }; /** - * Create the HTML DOM for the DataAxis + * 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, ...) */ - 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; + StepNumber.prototype.setStep = function(step, prettyStep) { + if (step === undefined || step <= 0) + return; - this.dom.lineContainer = document.createElement('div'); - this.dom.lineContainer.style.width = '100%'; - this.dom.lineContainer.style.height = this.height; - this.dom.lineContainer.style.position = 'relative'; + if (prettyStep !== undefined) + this.prettyStep = prettyStep; - // 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); + if (this.prettyStep === true) + this._step = StepNumber.calculatePrettyStep(step); + else + this._step = step; }; - DataAxis.prototype._redrawGroupIcons = function () { - DOMutil.prepareElements(this.svgElements); + /** + * 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;}; - var x; - var iconWidth = this.options.iconWidth; - var iconHeight = 15; - var iconOffset = 4; - var y = iconOffset + 0.5 * iconHeight; + // 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))); - if (this.options.orientation == 'left') { - x = iconOffset; - } - else { - x = this.width - iconWidth - iconOffset; - } + // 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; - for (var groupId in this.groups) { - if (this.groups.hasOwnProperty(groupId)) { - if (this.groups[groupId].visible == true && (this.linegraphOptions.visibility[groupId] === undefined || this.linegraphOptions.visibility[groupId] == true)) { - this.groups[groupId].drawIcon(x, y, this.svgElements, this.svg, iconWidth, iconHeight); - y += iconHeight + iconOffset; - } - } + // for safety + if (prettyStep <= 0) { + prettyStep = 1; } - DOMutil.cleanupElements(this.svgElements); - this.iconsRemoved = false; + return prettyStep; }; - DataAxis.prototype._cleanupIcons = function() { - if (this.iconsRemoved == false) { - DOMutil.prepareElements(this.svgElements); - DOMutil.cleanupElements(this.svgElements); - this.iconsRemoved = true; - } - } - /** - * Create the HTML DOM for the DataAxis + * returns the current value of the step + * @return {Number} current value */ - DataAxis.prototype.show = function() { - this.hidden = false; - 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); - } + StepNumber.prototype.getCurrent = function () { + return parseFloat(this._current.toPrecision(this.precision)); }; /** - * Create the HTML DOM for the DataAxis + * returns the current step size + * @return {Number} current step size */ - DataAxis.prototype.hide = function() { - this.hidden = true; - if (this.dom.frame.parentNode) { - this.dom.frame.parentNode.removeChild(this.dom.frame); - } + StepNumber.prototype.getStep = function () { + return this._step; + }; - if (this.dom.lineContainer.parentNode) { - this.dom.lineContainer.parentNode.removeChild(this.dom.lineContainer); - } + /** + * 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; }; /** - * Set a range (start and end) - * @param end - * @param start - * @param end + * Do a step, add the step size to the current value */ - DataAxis.prototype.setRange = function (start, end) { - if (this.master == false && this.options.alignZeros == true && this.zeroCrossing != -1) { - if (start > 0) { - start = 0; - } - } - this.range.start = start; - this.range.end = end; + StepNumber.prototype.next = function () { + this._current += this._step; }; /** - * Repaint the component - * @return {boolean} Returns true if the component is resized + * Returns true whether the end is reached + * @return {boolean} True if the current value has passed the end value. */ - DataAxis.prototype.redraw = function () { - var resized = false; - var activeGroups = 0; - - // Make sure the line container adheres to the vertical scrolling. - this.dom.lineContainer.style.top = this.body.domProps.scrollTop + 'px'; + StepNumber.prototype.end = function () { + return (this._current > this._end); + }; - for (var groupId in this.groups) { - if (this.groups.hasOwnProperty(groupId)) { - if (this.groups[groupId].visible == true && (this.linegraphOptions.visibility[groupId] === undefined || this.linegraphOptions.visibility[groupId] == true)) { - activeGroups++; - } - } - } - if (this.amountOfGroups == 0 || activeGroups == 0) { - this.hide(); - } - else { - this.show(); - this.height = Number(this.linegraphSVG.style.height.replace("px","")); + module.exports = StepNumber; - // 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; - var props = this.props; - var frame = this.dom.frame; +/***/ }, +/* 18 */ +/***/ function(module, exports, __webpack_require__) { - // update classname - frame.className = 'dataaxis'; + var Emitter = __webpack_require__(11); + var Hammer = __webpack_require__(19); + var util = __webpack_require__(1); + var DataSet = __webpack_require__(7); + var DataView = __webpack_require__(9); + var Range = __webpack_require__(21); + var Core = __webpack_require__(25); + var TimeAxis = __webpack_require__(38); + var CurrentTime = __webpack_require__(39); + var CustomTime = __webpack_require__(41); + var ItemSet = __webpack_require__(26); - // calculate character width and height - this._calculateCharSize(); + /** + * Create a timeline visualization + * @param {HTMLElement} container + * @param {vis.DataSet | vis.DataView | Array | google.visualization.DataTable} [items] + * @param {vis.DataSet | vis.DataView | Array | google.visualization.DataTable} [groups] + * @param {Object} [options] See Timeline.setOptions for the available options. + * @constructor + * @extends Core + */ + function Timeline (container, items, groups, options) { + if (!(this instanceof Timeline)) { + throw new SyntaxError('Constructor must be called with the new operator'); + } - var orientation = this.options.orientation; - var showMinorLabels = this.options.showMinorLabels; - var showMajorLabels = this.options.showMajorLabels; + // if the third element is options, the forth is groups (optionally); + if (!(Array.isArray(groups) || groups instanceof DataSet || groups instanceof DataView) && groups instanceof Object) { + var forthArgument = options; + options = groups; + groups = forthArgument; + } - // determine the width and height of the elements for the axis - props.minorLabelHeight = showMinorLabels ? props.minorCharHeight : 0; - props.majorLabelHeight = showMajorLabels ? props.majorCharHeight : 0; + var me = this; + this.defaultOptions = { + start: null, + end: null, - 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; + autoResize: true, - // 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"; - this.props.width = this.body.domProps.left.width; - this.props.height = this.body.domProps.left.height; - } - 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"; - this.props.width = this.body.domProps.right.width; - this.props.height = this.body.domProps.right.height; - } + orientation: 'bottom', + width: null, + height: null, + maxHeight: null, + minHeight: null + }; + this.options = util.deepExtend({}, this.defaultOptions); - resized = this._redrawLabels(); - resized = this._isResized() || resized; + // Create the DOM, props, and emitter + this._create(container); - if (this.options.icons == true) { - this._redrawGroupIcons(); - } - else { - this._cleanupIcons(); - } + // all components listed here will be repainted automatically + this.components = []; - this._redrawTitle(orientation); - } - return resized; - }; + this.body = { + dom: this.dom, + domProps: this.props, + emitter: { + on: this.on.bind(this), + off: this.off.bind(this), + emit: this.emit.bind(this) + }, + hiddenDates: [], + util: { + getScale: function () { + return me.timeAxis.step.scale; + }, + getStep: function () { + return me.timeAxis.step.step; + }, - /** - * Repaint major and minor text labels and vertical grid lines - * @private - */ - DataAxis.prototype._redrawLabels = function () { - var resized = false; - DOMutil.prepareElements(this.DOMelements.lines); - DOMutil.prepareElements(this.DOMelements.labels); + 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) + } + }; - var orientation = this.options['orientation']; + // range + this.range = new Range(this.body); + this.components.push(this.range); + this.body.range = this.range; - // 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; + // time axis + this.timeAxis = new TimeAxis(this.body); + this.components.push(this.timeAxis); - var step = new DataStep( - this.range.start, - this.range.end, - minimumStep, - this.dom.frame.offsetHeight, - this.options.customRange[this.options.orientation], - this.master == false && this.options.alignZeros // doess the step have to align zeros? only if not master and the options is on - ); + // current time bar + this.currentTime = new CurrentTime(this.body); + this.components.push(this.currentTime); - this.step = step; - // get the distance in pixels for a step - // dead space is space that is "left over" after a step - var stepPixels = (this.dom.frame.offsetHeight - (step.deadSpace * (this.dom.frame.offsetHeight / step.marginRange))) / (((step.marginRange - step.deadSpace) / step.step)); + // 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.stepPixels = stepPixels; + // item set + this.itemSet = new ItemSet(this.body); + this.components.push(this.itemSet); - var amountOfSteps = this.height / stepPixels; - var stepDifference = 0; + this.itemsData = null; // DataSet + this.groupsData = null; // DataSet - // the slave axis needs to use the same horizontal lines as the master axis. - if (this.master == false) { - stepPixels = this.stepPixelsForced; - stepDifference = Math.round((this.dom.frame.offsetHeight / stepPixels) - amountOfSteps); - for (var i = 0; i < 0.5 * stepDifference; i++) { - step.previous(); - } - amountOfSteps = this.height / stepPixels; + // apply options + if (options) { + this.setOptions(options); + } - if (this.zeroCrossing != -1 && this.options.alignZeros == true) { - var zeroStepDifference = (step.marginEnd / step.step) - this.zeroCrossing; - if (zeroStepDifference > 0) { - for (var i = 0; i < zeroStepDifference; i++) {step.next();} - } - else if (zeroStepDifference < 0) { - for (var i = 0; i < -zeroStepDifference; i++) {step.previous();} - } - } + // IMPORTANT: THIS HAPPENS BEFORE SET ITEMS! + if (groups) { + this.setGroups(groups); + } + + // create itemset + if (items) { + this.setItems(items); } else { - amountOfSteps += 0.25; + this._redraw(); } + } + // Extend the functionality from Core + Timeline.prototype = new Core(); - this.valueAtZero = step.marginEnd; - var marginStartPos = 0; + /** + * Force a redraw. The size of all items will be recalculated. + * Can be useful to manually redraw when option autoResize=false and the window + * has been resized, or when the items CSS has been changed. + */ + Timeline.prototype.redraw = function() { + this.itemSet && this.itemSet.markDirty({refreshItems: true}); + this._redraw(); + }; - // do not draw the first label - var max = 1; + /** + * Set items + * @param {vis.DataSet | Array | google.visualization.DataTable | null} items + */ + Timeline.prototype.setItems = function(items) { + var initialLoad = (this.itemsData == null); - // Get the number of decimal places - var decimals; - if(this.options.format[orientation] !== undefined) { - decimals = this.options.format[orientation].decimals; + // 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' + } + }); } - this.maxLabelSize = 0; - var y = 0; - while (max < Math.round(amountOfSteps)) { - step.next(); - 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(decimals), orientation, 'yAxis minor', this.props.minorCharHeight); - } + // set items + this.itemsData = newDataSet; + this.itemSet && this.itemSet.setItems(newDataSet); - 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(decimals), orientation, 'yAxis major', this.props.majorCharHeight); + if (initialLoad) { + if (this.options.start != undefined || this.options.end != undefined) { + if (this.options.start == undefined || this.options.end == undefined) { + var dataRange = this._getDataRange(); } - this._redrawLine(y, orientation, 'grid horizontal major', this.options.majorLinesOffset, this.props.majorLineWidth); + + var start = this.options.start != undefined ? this.options.start : dataRange.start; + var end = this.options.end != undefined ? this.options.end : dataRange.end; + + this.setWindow(start, end, {animate: false}); } else { - this._redrawLine(y, orientation, 'grid horizontal minor', this.options.minorLinesOffset, this.props.minorLineWidth); - } - - if (this.master == true && step.current == 0) { - this.zeroCrossing = max; + this.fit({animate: false}); } - - max++; - } - - if (this.master == false) { - this.conversionFactor = y / (this.valueAtZero - step.current); - } - else { - this.conversionFactor = this.dom.frame.offsetHeight / step.marginRange; - } - - // Note that title is rotated, so we're using the height, not width! - var titleWidth = 0; - if (this.options.title[orientation] !== undefined && this.options.title[orientation].text !== undefined) { - titleWidth = this.props.titleCharHeight; } - var offset = this.options.icons == true ? Math.max(this.options.iconWidth, titleWidth) + this.options.labelOffsetX + 15 : titleWidth + this.options.labelOffsetX + 15; + }; - // this will resize the yAxis to accommodate the labels. - if (this.maxLabelSize > (this.width - offset) && this.options.visible == true) { - this.width = this.maxLabelSize + offset; - this.options.width = this.width + "px"; - DOMutil.cleanupElements(this.DOMelements.lines); - DOMutil.cleanupElements(this.DOMelements.labels); - this.redraw(); - resized = true; + /** + * Set groups + * @param {vis.DataSet | Array | google.visualization.DataTable} groups + */ + Timeline.prototype.setGroups = function(groups) { + // convert to type DataSet when needed + var newDataSet; + if (!groups) { + newDataSet = null; } - // this will resize the yAxis if it is too big for the labels. - else if (this.maxLabelSize < (this.width - offset) && this.options.visible == true && this.width > this.minWidth) { - this.width = Math.max(this.minWidth,this.maxLabelSize + offset); - this.options.width = this.width + "px"; - DOMutil.cleanupElements(this.DOMelements.lines); - DOMutil.cleanupElements(this.DOMelements.labels); - this.redraw(); - resized = true; + else if (groups instanceof DataSet || groups instanceof DataView) { + newDataSet = groups; } else { - DOMutil.cleanupElements(this.DOMelements.lines); - DOMutil.cleanupElements(this.DOMelements.labels); - resized = false; + // turn an array into a dataset + newDataSet = new DataSet(groups); } - return resized; - }; - - DataAxis.prototype.convertValue = function (value) { - var invertedValue = this.valueAtZero - value; - var convertedValue = invertedValue * this.conversionFactor; - return convertedValue; + this.groupsData = newDataSet; + this.itemSet.setGroups(newDataSet); }; /** - * Create a label for the axis at position x - * @private - * @param y - * @param text - * @param orientation - * @param className - * @param characterHeight + * Set selected items by their id. Replaces the current selection + * Unknown id's are silently ignored. + * @param {string[] | string} [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. + * @param {Object} [options] Available options: + * `focus: boolean` + * If true, focus will be set to the selected item(s) + * `animate: boolean | number` + * If true (default), the range is animated + * smoothly to the new window. + * If a number, the number is taken as duration + * for the animation. Default duration is 500 ms. + * Only applicable when option focus is true. */ - 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'; - - text += ''; + Timeline.prototype.setSelection = function(ids, options) { + this.itemSet && this.itemSet.setSelection(ids); - var largestWidth = Math.max(this.props.majorCharWidth,this.props.minorCharWidth); - if (this.maxLabelSize < text.length * largestWidth) { - this.maxLabelSize = text.length * largestWidth; + if (options && options.focus) { + this.focus(ids, options); } }; /** - * Create a minor line for the axis at position y - * @param y - * @param orientation - * @param className - * @param offset - * @param width + * Get the selected items by their id + * @return {Array} ids The ids of the selected items */ - DataAxis.prototype._redrawLine = function (y, orientation, className, offset, width) { - if (this.master == true) { - var line = DOMutil.getDOMElement('div',this.DOMelements.lines, this.dom.lineContainer);//this.dom.redundant.lines.shift(); - line.className = className; - line.innerHTML = ''; - - if (orientation == 'left') { - line.style.left = (this.width - offset) + 'px'; - } - else { - line.style.right = (this.width - offset) + 'px'; - } - - line.style.width = width + 'px'; - line.style.top = y + 'px'; - } + Timeline.prototype.getSelection = function() { + return this.itemSet && this.itemSet.getSelection() || []; }; /** - * Create a title for the axis - * @private - * @param orientation + * Adjust the visible window such that the selected item (or multiple items) + * are centered on screen. + * @param {String | String[]} id An item id or array with item ids + * @param {Object} [options] Available options: + * `animate: boolean | number` + * If true (default), the range is animated + * smoothly to the new window. + * If a number, the number is taken as duration + * for the animation. Default duration is 500 ms. + * Only applicable when option focus is true */ - DataAxis.prototype._redrawTitle = function (orientation) { - DOMutil.prepareElements(this.DOMelements.title); + Timeline.prototype.focus = function(id, options) { + if (!this.itemsData || id == undefined) return; - // Check if the title is defined for this axes - if (this.options.title[orientation] !== undefined && this.options.title[orientation].text !== undefined) { - var title = DOMutil.getDOMElement('div', this.DOMelements.title, this.dom.frame); - title.className = 'yAxis title ' + orientation; - title.innerHTML = this.options.title[orientation].text; + var ids = Array.isArray(id) ? id : [id]; - // Add style - if provided - if (this.options.title[orientation].style !== undefined) { - util.addCssText(title, this.options.title[orientation].style); + // get the specified item(s) + var itemsData = this.itemsData.getDataSet().get(ids, { + type: { + start: 'Date', + end: 'Date' } + }); - if (orientation == 'left') { - title.style.left = this.props.titleCharHeight + 'px'; + // calculate minimum start and maximum end of specified items + var start = null; + var end = null; + itemsData.forEach(function (itemData) { + var s = itemData.start.valueOf(); + var e = 'end' in itemData ? itemData.end.valueOf() : itemData.start.valueOf(); + + if (start === null || s < start) { + start = s; } - else { - title.style.right = this.props.titleCharHeight + 'px'; + + if (end === null || e > end) { + end = e; } + }); - title.style.width = this.height + 'px'; - } + if (start !== null && end !== null) { + // calculate the new middle and interval for the window + var middle = (start + end) / 2; + var interval = Math.max((this.range.end - this.range.start), (end - start) * 1.1); - // we need to clean up in case we did not use all elements. - DOMutil.cleanupElements(this.DOMelements.title); + var animate = (options && options.animate !== undefined) ? options.animate : true; + this.range.setRange(middle - interval / 2, middle + interval / 2, animate); + } }; - - - /** - * 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 + * 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 */ - 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); + Timeline.prototype.getItemRange = function() { + // calculate min from start filed + var dataset = this.itemsData.getDataSet(), + min = null, + max = null; - this.props.minorCharHeight = measureCharMinor.clientHeight; - this.props.minorCharWidth = measureCharMinor.clientWidth; + 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 - this.dom.frame.removeChild(measureCharMinor); + // 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()); + } + } } - 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); + return { + min: (min != null) ? new Date(min) : null, + max: (max != null) ? new Date(max) : null + }; + }; - this.props.majorCharHeight = measureCharMajor.clientHeight; - this.props.majorCharWidth = measureCharMajor.clientWidth; - this.dom.frame.removeChild(measureCharMajor); - } + module.exports = Timeline; - if (!('titleCharHeight' in this.props)) { - var textTitle = document.createTextNode('0'); - var measureCharTitle = document.createElement('div'); - measureCharTitle.className = 'yAxis title measure'; - measureCharTitle.appendChild(textTitle); - this.dom.frame.appendChild(measureCharTitle); - this.props.titleCharHeight = measureCharTitle.clientHeight; - this.props.titleCharWidth = measureCharTitle.clientWidth; +/***/ }, +/* 19 */ +/***/ function(module, exports, __webpack_require__) { - this.dom.frame.removeChild(measureCharTitle); + // 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__(20); + } + else { + module.exports = function () { + throw Error('hammer.js is only available in a browser, not in node.js.'); } - }; - - module.exports = DataAxis; + } /***/ }, -/* 24 */ +/* 20 */ /***/ function(module, exports, __webpack_require__) { - var util = __webpack_require__(1); - var DOMutil = __webpack_require__(2); - var Line = __webpack_require__(52); - var Bar = __webpack_require__(51); - var Points = __webpack_require__(53); + 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'; /** - * /** - * @param {object} group | the object of the group from the dataset - * @param {string} groupId | ID of the group - * @param {object} options | the default options - * @param {array} groupsUsingDefaultStyles | this array has one entree. - * It is passed as an array so it is passed by reference. - * It enumerates through the default styles - * @constructor + * @main + * @module hammer + * + * @class Hammer + * @static */ - 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 loads a reference to all items in this group into this group. - * @param {array} items + * Hammer, use this to create instances + * ```` + * var hammertime = new Hammer(myElement); + * ```` + * + * @method Hammer + * @param {HTMLElement} element + * @param {Object} [options={}] + * @return {Hammer.Instance} */ - 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 = []; - } + var Hammer = function Hammer(element, options) { + return new Hammer.Instance(element, options || {}); }; - /** - * this is used for plotting barcharts, this way, we only have to calculate it once. - * @param pos + * version, as defined in package.json + * the value will be set at each build + * @property VERSION + * @final + * @type {String} */ - GraphGroup.prototype.setZeroPosition = function(pos) { - this.zeroPosition = pos; - }; - + Hammer.VERSION = '1.1.3'; /** - * set the options of the graph group over the default options. - * @param options + * 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} */ - GraphGroup.prototype.setOptions = function(options) { - if (options !== undefined) { - var fields = ['sampling','style','sort','yAxisOrientation','barChart']; - util.selectiveDeepExtend(fields, this.options, options); + 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', - util.mergeOptions(this.options, options,'catmullRom'); - util.mergeOptions(this.options, options,'drawPoints'); - util.mergeOptions(this.options, options,'shaded'); + /** + * 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', - 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; - } - } - } - } - } + /** + * 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.options.style == 'line') { - this.type = new Line(this.id, this.options); - } - else if (this.options.style == 'bar') { - this.type = new Bar(this.id, this.options); - } - else if (this.options.style == 'points') { - this.type = new Points(this.id, this.options); - } - }; + /** + * 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 updates the current group class with the latest group dataset entree, used in _updateGroup in linegraph - * @param group - */ - 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.style = group.style; - this.setOptions(group.options); + /** + * 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)' + } }; - /** - * draw the icon for the legend. - * - * @param x - * @param y - * @param JSONcontainer - * @param SVGcontainer - * @param iconWidth - * @param iconHeight + * hammer document where the base events are added at + * @property DOCUMENT + * @type {HTMLElement} + * @default window.document */ - GraphGroup.prototype.drawIcon = function(x, y, JSONcontainer, SVGcontainer, iconWidth, iconHeight) { - var fillHeight = iconHeight * 0.5; - var path, fillPath; - - var outline = DOMutil.getSVGElement("rect", JSONcontainer, SVGcontainer); - outline.setAttributeNS(null, "x", x); - outline.setAttributeNS(null, "y", y - fillHeight); - outline.setAttributeNS(null, "width", iconWidth); - outline.setAttributeNS(null, "height", 2*fillHeight); - outline.setAttributeNS(null, "class", "outline"); - - if (this.options.style == 'line') { - path = DOMutil.getSVGElement("path", JSONcontainer, SVGcontainer); - path.setAttributeNS(null, "class", this.className); - if(this.style !== undefined) { - path.setAttributeNS(null, "style", this.style); - } - - path.setAttributeNS(null, "d", "M" + x + ","+y+" L" + (x + iconWidth) + ","+y+""); - if (this.options.shaded.enabled == true) { - fillPath = DOMutil.getSVGElement("path", JSONcontainer, SVGcontainer); - if (this.options.shaded.orientation == 'top') { - fillPath.setAttributeNS(null, "d", "M"+x+", " + (y - fillHeight) + - "L"+x+","+y+" L"+ (x + iconWidth) + ","+y+" L"+ (x + iconWidth) + "," + (y - fillHeight)); - } - else { - fillPath.setAttributeNS(null, "d", "M"+x+","+y+" " + - "L"+x+"," + (y + fillHeight) + " " + - "L"+ (x + iconWidth) + "," + (y + fillHeight) + - "L"+ (x + iconWidth) + ","+y); - } - fillPath.setAttributeNS(null, "class", this.className + " iconFill"); - } - - if (this.options.drawPoints.enabled == true) { - DOMutil.drawPoint(x + 0.5 * iconWidth,y, this, JSONcontainer, SVGcontainer); - } - } - else { - var barWidth = Math.round(0.3 * iconWidth); - var bar1Height = Math.round(0.4 * iconHeight); - var bar2Height = Math.round(0.75 * iconHeight); - - var offset = Math.round((iconWidth - (2 * barWidth))/3); - - DOMutil.drawBar(x + 0.5*barWidth + offset , y + fillHeight - bar1Height - 1, barWidth, bar1Height, this.className + ' bar', JSONcontainer, SVGcontainer); - DOMutil.drawBar(x + 1.5*barWidth + offset + 2, y + fillHeight - bar2Height - 1, barWidth, bar2Height, this.className + ' bar', JSONcontainer, SVGcontainer); - } - }; - + Hammer.DOCUMENT = document; /** - * return the legend entree for this group. - * - * @param iconWidth - * @param iconHeight - * @returns {{icon: HTMLElement, label: (group.content|*|string), orientation: (.options.yAxisOrientation|*)}} + * detect support for pointer events + * @property HAS_POINTEREVENTS + * @type {Boolean} */ - 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}; - } - - GraphGroup.prototype.getYRange = function(groupData) { - return this.type.getYRange(groupData); - } - - GraphGroup.prototype.draw = function(dataset, group, framework) { - this.type.draw(dataset, group, framework); - } - - - module.exports = GraphGroup; - - -/***/ }, -/* 25 */ -/***/ function(module, exports, __webpack_require__) { - - var util = __webpack_require__(1); - var stack = __webpack_require__(18); - var RangeItem = __webpack_require__(35); + Hammer.HAS_POINTEREVENTS = navigator.pointerEnabled || navigator.msPointerEnabled; /** - * @constructor Group - * @param {Number | String} groupId - * @param {Object} data - * @param {ItemSet} itemSet + * detect support for touch events + * @property HAS_TOUCHEVENTS + * @type {Boolean} */ - function Group (groupId, data, itemSet) { - this.groupId = groupId; - this.subgroups = {}; - this.subgroupIndex = 0; - this.subgroupOrderer = data && data.subgroupOrder; - this.itemSet = itemSet; - - this.dom = {}; - this.props = { - label: { - width: 0, - height: 0 - } - }; - this.className = null; + Hammer.HAS_TOUCHEVENTS = ('ontouchstart' in window); - this.items = {}; // items filtered by groupId of this group - this.visibleItems = []; // items currently visible in window - this.orderedItems = { - byStart: [], - byEnd: [] - }; - this.checkRangedItems = false; // needed to refresh the ranged items if the window is programatically changed with NO overlap. - var me = this; - this.itemSet.body.emitter.on("checkRangedItems", function () { - me.checkRangedItems = true; - }) + /** + * detect mobile browsers + * @property IS_MOBILE + * @type {Boolean} + */ + Hammer.IS_MOBILE = /mobile|tablet|ip(ad|hone|od)|android|silk/i.test(navigator.userAgent); - this._create(); + /** + * 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; - this.setData(data); - } + /** + * interval in which Hammer recalculates current velocity/direction/angle in ms + * @property CALCULATE_INTERVAL + * @type {Number} + * @default 25 + */ + Hammer.CALCULATE_INTERVAL = 25; /** - * Create DOM elements for the group + * 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} */ - 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; - - 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'; // TODO: ask jos why this is not none? - this.dom.marker.innerHTML = '?'; - this.dom.background.appendChild(this.dom.marker); - }; + var EVENT_TYPES = {}; /** - * Set the group data for this group - * @param {Object} data Group data, can contain properties content and className + * direction strings, for safe comparisons + * @property DIRECTION_DOWN|LEFT|UP|RIGHT + * @final + * @type {String} + * @default 'down' 'left' 'up' 'right' */ - Group.prototype.setData = function(data) { - // update contents - var content = data && data.content; - if (content instanceof Element) { - this.dom.inner.appendChild(content); - } - else if (content !== undefined && content !== null) { - this.dom.inner.innerHTML = content; - } - else { - this.dom.inner.innerHTML = this.groupId || ''; // groupId can be null - } - - // 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, this.className); - util.removeClassName(this.dom.foreground, this.className); - util.removeClassName(this.dom.background, this.className); - util.removeClassName(this.dom.axis, this.className); - } - util.addClassName(this.dom.label, className); - util.addClassName(this.dom.foreground, className); - util.addClassName(this.dom.background, className); - util.addClassName(this.dom.axis, className); - this.className = className; - } - - // update style - if (this.style) { - util.removeCssText(this.dom.label, this.style); - this.style = null; - } - if (data && data.style) { - util.addCssText(this.dom.label, data.style); - this.style = data.style; - } - }; + 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'; /** - * Get the width of the group label - * @return {number} width + * pointertype strings, for safe comparisons + * @property POINTER_MOUSE|TOUCH|PEN + * @final + * @type {String} + * @default 'mouse' 'touch' 'pen' */ - Group.prototype.getLabelWidth = function() { - return this.props.label.width; - }; - + var POINTER_MOUSE = Hammer.POINTER_MOUSE = 'mouse'; + var POINTER_TOUCH = Hammer.POINTER_TOUCH = 'touch'; + var POINTER_PEN = Hammer.POINTER_PEN = 'pen'; /** - * 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 + * eventtypes + * @property EVENT_START|MOVE|END|RELEASE|TOUCH + * @final + * @type {String} + * @default 'start' 'change' 'move' 'end' 'release' 'touch' */ - Group.prototype.redraw = function(range, margin, restack) { - var resized = false; - - this.visibleItems = this._updateVisibleItems(this.orderedItems, this.visibleItems, range); - - // force recalculation of the height of the items when the marker height changed - // (due to the Timeline being attached to the DOM or changed from display:none to visible) - var markerHeight = this.dom.marker.clientHeight; - if (markerHeight != this.lastMarkerHeight) { - this.lastMarkerHeight = markerHeight; - - util.forEach(this.items, function (item) { - item.dirty = true; - if (item.displayed) item.redraw(); - }); - - 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, this.subgroups); - } - - // recalculate the height of the group - var height = this._calculateHeight(margin); - - // 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; + 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'; - // 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 the window events are set... + * @property READY + * @writeOnce + * @type {Boolean} + * @default false + */ + Hammer.READY = false; - // 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(margin); - } + /** + * plugins namespace + * @property plugins + * @type {Object} + */ + Hammer.plugins = Hammer.plugins || {}; - return resized; - }; + /** + * gestures namespace + * see `/gestures` for the definitions + * @property gestures + * @type {Object} + */ + Hammer.gestures = Hammer.gestures || {}; /** - * recalculate the height of the group - * @param {{item: {horizontal: number, vertical: number}, axis: number}} margin - * @returns {number} Returns the height + * setup events to detect gestures on the document + * this function is called when creating an new instance * @private */ - Group.prototype._calculateHeight = function (margin) { - // recalculate the height of the group - var height; - var visibleItems = this.visibleItems; - //var visibleSubgroups = []; - //this.visibleSubgroups = 0; - this.resetSubgroups(); - var me = this; - 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 (item.data.subgroup !== undefined) { - me.subgroups[item.data.subgroup].height = Math.max(me.subgroups[item.data.subgroup].height,item.height); - me.subgroups[item.data.subgroup].visible = true; - //if (visibleSubgroups.indexOf(item.data.subgroup) == -1){ - // visibleSubgroups.push(item.data.subgroup); - // me.visibleSubgroups += 1; - //} - } - }); - 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; - }); + function setup() { + if(Hammer.READY) { + return; } - height = max + margin.item.vertical / 2; - } - else { - height = margin.axis + margin.item.vertical; - } - height = Math.max(height, this.props.label.height); - - return height; - }; - /** - * Show this group: attach to the DOM - */ - Group.prototype.show = function() { - if (!this.dom.label.parentNode) { - this.itemSet.dom.labelSet.appendChild(this.dom.label); - } + // find what eventtypes we add listeners to + Event.determineEventTypes(); - if (!this.dom.foreground.parentNode) { - this.itemSet.dom.foreground.appendChild(this.dom.foreground); - } + // Register all gestures inside Hammer.gestures + Utils.each(Hammer.gestures, function(gesture) { + Detection.register(gesture); + }); - if (!this.dom.background.parentNode) { - this.itemSet.dom.background.appendChild(this.dom.background); - } + // Add touch events on the document + Event.onTouch(Hammer.DOCUMENT, EVENT_MOVE, Detection.detect); + Event.onTouch(Hammer.DOCUMENT, EVENT_END, Detection.detect); - if (!this.dom.axis.parentNode) { - this.itemSet.dom.axis.appendChild(this.dom.axis); - } - }; + // Hammer is ready...! + Hammer.READY = true; + } /** - * Hide this group: remove from the DOM - */ - Group.prototype.hide = function() { - var label = this.dom.label; - if (label.parentNode) { - label.parentNode.removeChild(label); - } + * @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; + }, - var foreground = this.dom.foreground; - if (foreground.parentNode) { - foreground.parentNode.removeChild(foreground); - } + /** + * 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); + }, - var background = this.dom.background; - if (background.parentNode) { - background.parentNode.removeChild(background); - } + /** + * 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); + }, - var axis = this.dom.axis; - if (axis.parentNode) { - axis.parentNode.removeChild(axis); - } - }; + /** + * 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; - /** - * Add an item to the group - * @param {Item} item - */ - Group.prototype.add = function(item) { - this.items[item.id] = item; - item.setParent(this); + // 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; + } + } + } + }, - // add to - if (item.data.subgroup !== undefined) { - if (this.subgroups[item.data.subgroup] === undefined) { - this.subgroups[item.data.subgroup] = {height:0, visible: false, index:this.subgroupIndex, items: []}; - this.subgroupIndex++; - } - this.subgroups[item.data.subgroup].items.push(item); - } - this.orderSubgroups(); + /** + * find if a string contains the string using indexOf + * @method inStr + * @param {String} src + * @param {String} find + * @return {Boolean} found + */ + inStr: function inStr(src, find) { + return src.indexOf(find) > -1; + }, - if (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); - } - }; + /** + * 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; + } + }, - Group.prototype.orderSubgroups = function() { - if (this.subgroupOrderer !== undefined) { - var sortArray = []; - if (typeof this.subgroupOrderer == 'string') { - for (var subgroup in this.subgroups) { - sortArray.push({subgroup: subgroup, sortField: this.subgroups[subgroup].items[0].data[this.subgroupOrderer]}) - } - sortArray.sort(function (a, b) { - return a.sortField - b.sortField; - }) - } - else if (typeof this.subgroupOrderer == 'function') { - for (var subgroup in this.subgroups) { - sortArray.push(this.subgroups[subgroup].items[0].data); - } - sortArray.sort(this.subgroupOrderer); - } + /** + * 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); + }, - if (sortArray.length > 0) { - for (var i = 0; i < sortArray.length; i++) { - this.subgroups[sortArray[i].subgroup].index = i; - } - } - } - }; + /** + * 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; + }, - Group.prototype.resetSubgroups = function() { - for (var subgroup in this.subgroups) { - if (this.subgroups.hasOwnProperty(subgroup)) { - this.subgroups[subgroup].visible = 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; - /** - * Remove an item from the group - * @param {Item} item - */ - Group.prototype.remove = function(item) { - delete this.items[item.id]; - item.setParent(null); + // 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 + }; + } - // remove from visible items - var index = this.visibleItems.indexOf(item); - if (index != -1) this.visibleItems.splice(index, 1); + Utils.each(touches, function(touch) { + pageX.push(touch.pageX); + pageY.push(touch.pageY); + clientX.push(touch.clientX); + clientY.push(touch.clientY); + }); - // TODO: also remove from ordered items? - }; + 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 + }; + }, - /** - * Remove an item from the corresponding DataSet - * @param {Item} item - */ - Group.prototype.removeFromDataSet = function(item) { - this.itemSet.removeItem(item.id); - }; + /** + * 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; + }, - /** - * Reorder the items - */ - Group.prototype.order = function() { - var array = util.toArray(this.items); - var startArray = []; - var endArray = []; + /** + * 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); - for (var i = 0; i < array.length; i++) { - if (array[i].data.end !== undefined) { - endArray.push(array[i]); - } - startArray.push(array[i]); - } - this.orderedItems = { - byStart: startArray, - byEnd: endArray - }; + if(x >= y) { + return touch1.clientX - touch2.clientX > 0 ? DIRECTION_LEFT : DIRECTION_RIGHT; + } + return touch1.clientY - touch2.clientY > 0 ? DIRECTION_UP : DIRECTION_DOWN; + }, - stack.orderByStart(this.orderedItems.byStart); - stack.orderByEnd(this.orderedItems.byEnd); - }; + /** + * 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)); + }, - /** - * Update the visible items - * @param {{byStart: Item[], byEnd: Item[]}} orderedItems All items ordered by start date and by end date - * @param {Item[]} visibleItems The previously visible items. - * @param {{start: number, end: number}} range Visible range - * @return {Item[]} visibleItems The new visible items. - * @private - */ - Group.prototype._updateVisibleItems = function(orderedItems, oldVisibleItems, range) { - var visibleItems = []; - var visibleItemsLookup = {}; // we keep this to quickly look up if an item already exists in the list without using indexOf on visibleItems - var interval = (range.end - range.start) / 4; - var lowerBound = range.start - interval; - var upperBound = range.end + interval; - var item, i; + /** + * 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; + }, - // this function is used to do the binary search. - var searchFunction = function (value) { - if (value < lowerBound) {return -1;} - else if (value <= upperBound) {return 0;} - else {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; + }, - // first check if the items that were in view previously are still in view. - // IMPORTANT: this handles the case for the items with startdate before the window and enddate after the window! - // also cleans up invisible items. - if (oldVisibleItems.length > 0) { - for (i = 0; i < oldVisibleItems.length; i++) { - this._checkIfVisibleWithReference(oldVisibleItems[i], visibleItems, visibleItemsLookup, range); - } - } + /** + * 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; + }, - // we do a binary search for the items that have only start values. - var initialPosByStart = util.binarySearchCustom(orderedItems.byStart, searchFunction, 'data','start'); + /** + * 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); - // trace the visible items from the inital start pos both ways until an invisible item is found, we only look at the start values. - this._traceVisible(initialPosByStart, orderedItems.byStart, visibleItems, visibleItemsLookup, function (item) { - return (item.data.start < lowerBound || item.data.start > upperBound); - }); + 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); + } - // if the window has changed programmatically without overlapping the old window, the ranged items with start < lowerBound and end > upperbound are not shown. - // We therefore have to brute force check all items in the byEnd list - if (this.checkRangedItems == true) { - this.checkRangedItems = false; - for (i = 0; i < orderedItems.byEnd.length; i++) { - this._checkIfVisibleWithReference(orderedItems.byEnd[i], visibleItems, visibleItemsLookup, range); - } - } - else { - // we do a binary search for the items that have defined end times. - var initialPosByEnd = util.binarySearchCustom(orderedItems.byEnd, searchFunction, 'data','end'); + // test the style + if(p in element.style) { + element.style[p] = (toggle == null || toggle) && value || ''; + break; + } + } + }, - // trace the visible items from the inital start pos both ways until an invisible item is found, we only look at the end values. - this._traceVisible(initialPosByEnd, orderedItems.byEnd, visibleItems, visibleItemsLookup, function (item) { - return (item.data.end < lowerBound || item.data.end > upperBound); - }); - } + /** + * 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); + }); - // finally, we reposition all the visible items. - for (i = 0; i < visibleItems.length; i++) { - item = visibleItems[i]; - if (!item.displayed) item.show(); - // reposition item horizontally - item.repositionX(); - } + var falseFn = toggle && function() { + return false; + }; - // debug - //console.log("new line") - //if (this.groupId == null) { - // for (i = 0; i < orderedItems.byStart.length; i++) { - // item = orderedItems.byStart[i].data; - // console.log('start',i,initialPosByStart, item.start.valueOf(), item.content, item.start >= lowerBound && item.start <= upperBound,i == initialPosByStart ? "<------------------- HEREEEE" : "") - // } - // for (i = 0; i < orderedItems.byEnd.length; i++) { - // item = orderedItems.byEnd[i].data; - // console.log('rangeEnd',i,initialPosByEnd, item.end.valueOf(), item.content, item.end >= range.start && item.end <= range.end,i == initialPosByEnd ? "<------------------- HEREEEE" : "") - // } - //} + // also the disable onselectstart + if(props.userSelect == 'none') { + element.onselectstart = falseFn; + } + // and disable ondragstart + if(props.userDrag == 'none') { + element.ondragstart = falseFn; + } + }, - return visibleItems; + /** + * 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(); + }); + } }; - Group.prototype._traceVisible = function (initialPos, items, visibleItems, visibleItemsLookup, breakCondition) { - var item; - var i; - - if (initialPos != -1) { - for (i = initialPos; i >= 0; i--) { - item = items[i]; - if (breakCondition(item)) { - break; - } - else { - if (visibleItemsLookup[item.id] === undefined) { - visibleItemsLookup[item.id] = true; - visibleItems.push(item); - } - } - } - - for (i = initialPos + 1; i < items.length; i++) { - item = items[i]; - if (breakCondition(item)) { - break; - } - else { - if (visibleItemsLookup[item.id] === undefined) { - visibleItemsLookup[item.id] = true; - visibleItems.push(item); - } - } - } - } - } - /** - * 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 + * @module hammer */ - 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(); - } - }; - - /** - * 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 + * @class Event + * @static */ - Group.prototype._checkIfVisibleWithReference = function(item, visibleItems, visibleItemsLookup, range) { - if (item.isVisible(range)) { - if (visibleItemsLookup[item.id] === undefined) { - visibleItemsLookup[item.id] = true; - visibleItems.push(item); - } - } - else { - if (item.displayed) item.hide(); - } - }; - + 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, - module.exports = Group; + /** + * 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); + }); + }, -/***/ }, -/* 26 */ -/***/ function(module, exports, __webpack_require__) { + /** + * simple event unbinder with a hook and support for multiple types + * @method off + * @param {HTMLElement} element + * @param {String} type + * @param {Function} handler + * @param {Function} [hook] + * @param {Object} hook.type + */ + off: function off(element, type, handler, hook) { + var types = type.split(' '); + Utils.each(types, function(type) { + Utils.off(element, type, handler); + hook && hook(type); + }); + }, - var util = __webpack_require__(1); - var Group = __webpack_require__(25); + /** + * the core touch event handler. + * this finds out if we should to detect gestures + * @method onTouch + * @param {HTMLElement} element + * @param {String} eventType matches `EVENT_START|MOVE|END` + * @param {Function} handler + * @return onTouchHandler {Function} the core event handler + */ + onTouch: function onTouch(element, eventType, handler) { + var self = this; - /** - * @constructor BackgroundGroup - * @param {Number | String} groupId - * @param {Object} data - * @param {ItemSet} itemSet - */ - function BackgroundGroup (groupId, data, itemSet) { - Group.call(this, groupId, data, itemSet); + var onTouchHandler = function onTouchHandler(ev) { + var srcType = ev.type.toLowerCase(), + isPointer = Hammer.HAS_POINTEREVENTS, + isMouse = Utils.inStr(srcType, 'mouse'), + triggerType; - this.width = 0; - this.height = 0; - this.top = 0; - this.left = 0; - } + // if we are in a mouseevent, but there has been a touchevent triggered in this session + // we want to do nothing. simply break out of the event. + if(isMouse && self.preventMouseEvents) { + return; - BackgroundGroup.prototype = Object.create(Group.prototype); + // 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; + } - /** - * 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 - */ - BackgroundGroup.prototype.redraw = function(range, margin, restack) { - var resized = false; + // update the pointer event before entering the detection + if(isPointer && eventType != EVENT_END) { + PointerEvent.updatePointer(eventType, ev); + } - this.visibleItems = this._updateVisibleItems(this.orderedItems, this.visibleItems, range); + // we are in a touch/down state, so allowed detection of gestures + if(self.shouldDetect) { + triggerType = self.doDetect.call(self, ev, eventType, element, handler); + } - // calculate actual size - this.width = this.dom.background.offsetWidth; + // ...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 (just always zero for BackgroundGroup - this.dom.background.style.height = '0'; + 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(margin); - } + 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 - */ - BackgroundGroup.prototype.show = function() { - if (!this.dom.background.parentNode) { - this.itemSet.dom.background.appendChild(this.dom.background); - } - }; + // 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; - module.exports = BackgroundGroup; + // keep track of how many touches have been removed + changedLength = touchList.length - ((ev.changedTouches) ? ev.changedTouches.length : 1); + } + // 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; + } -/***/ }, -/* 27 */ -/***/ function(module, exports, __webpack_require__) { + // detection has been started, we keep track of this, see above + this.started = true; - var Hammer = __webpack_require__(45); - var util = __webpack_require__(1); - var DataSet = __webpack_require__(3); - var DataView = __webpack_require__(4); - var TimeStep = __webpack_require__(19); - var Component = __webpack_require__(20); - var Group = __webpack_require__(25); - var BackgroundGroup = __webpack_require__(26); - var BoxItem = __webpack_require__(33); - var PointItem = __webpack_require__(34); - var RangeItem = __webpack_require__(35); - var BackgroundItem = __webpack_require__(32); + // 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); + } - var UNGROUPED = '__ungrouped__'; // reserved group id for ungrouped items - var BACKGROUND = '__background__'; // reserved group id for background items without group + // trigger a change (TOUCH, RELEASE) event, this means the length of the touches changed + if(triggerChange) { + evData.changedLength = changedLength; + evData.eventType = triggerChange; - /** - * 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; + handler.call(Detection, evData); - this.defaultOptions = { - type: null, // 'box', 'point', 'range', 'background' - orientation: 'bottom', // 'top' or 'bottom' - align: 'auto', // alignment of box items - stack: true, - groupOrder: null, + evData.eventType = triggerType; + delete evData.changedLength; + } - selectable: true, - editable: { - updateTime: false, - updateGroup: false, - add: false, - remove: false - }, + // trigger the END event + if(triggerType == EVENT_END) { + handler.call(Detection, evData); - snap: TimeStep.snap, + // ...and we are done with the detection + // so reset everything to start each detection totally fresh + this.started = false; + } - onAdd: function (item, callback) { - callback(item); - }, - onUpdate: function (item, callback) { - callback(item); - }, - onMove: function (item, callback) { - callback(item); - }, - onRemove: function (item, callback) { - callback(item); - }, - onMoving: function (item, callback) { - callback(item); + return triggerType; }, - margin: { - item: { - horizontal: 10, - vertical: 10 - }, - axis: 20 + /** + * 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; }, - padding: 5 - }; - // options is shared by this ItemSet and all its items - this.options = util.extend({}, this.defaultOptions); + /** + * 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(); + } - // options for getting items from the DataSet with the correct type - this.itemOptions = { - type: {start: 'Date', end: 'Date'} - }; + // get the touchlist + if(ev.touches) { + if(eventType == EVENT_MOVE) { + return ev.touches; + } - this.conversion = { - toScreen: body.util.toScreen, - toTime: body.util.toTime - }; - this.dom = {}; - this.props = {}; - this.hammer = null; + var identifiers = []; + var concat = [].concat(Utils.toArray(ev.touches), Utils.toArray(ev.changedTouches)); + var touchList = []; - var me = this; - this.itemsData = null; // DataSet - this.groupsData = null; // DataSet + Utils.each(concat, function(touch) { + if(Utils.inArray(identifiers, touch.identifier) === false) { + touchList.push(touch); + } + identifiers.push(touch.identifier); + }); - // listeners for the DataSet of the items - this.itemListeners = { - 'add': function (event, params, senderId) { - me._onAdd(params.items); - }, - 'update': function (event, params, senderId) { - me._onUpdate(params.items); - }, - 'remove': function (event, params, senderId) { - me._onRemove(params.items); - } - }; + return touchList; + } - // 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); + // make fake touchList from mouse position + ev.identifier = 1; + return [ev]; }, - 'remove': function (event, params, senderId) { - me._onRemoveGroups(params.items); - } - }; - this.items = {}; // object with an Item for every data item - this.groups = {}; // Group object for every group - this.groupIds = []; + /** + * 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; + } - this.selection = []; // list with the ids of all selected nodes - this.stackDirty = true; // if true, all items will be restacked on next redraw + return { + center: Utils.getCenter(touches), + timeStamp: Date.now(), + target: ev.target, + touches: touches, + eventType: eventType, + pointerType: pointerType, + srcEvent: ev, - this.touchParams = {}; // stores properties while dragging - // create the HTML DOM + /** + * 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(); + }, - this._create(); + /** + * stop bubbling the event up to its parents + */ + stopPropagation: function() { + this.srcEvent.stopPropagation(); + }, - this.setOptions(options); - } + /** + * immediately stop gesture detection + * might be useful after a swipe was detected + * @return {*} + */ + stopDetect: function() { + return Detection.stopDetect(); + } + }; + } + }; - ItemSet.prototype = new Component(); - - // available item types will be registered here - ItemSet.types = { - background: BackgroundItem, - box: BoxItem, - range: RangeItem, - point: PointItem - }; /** - * Create the HTML DOM for the ItemSet + * @module hammer + * + * @class PointerEvent + * @static */ - ItemSet.prototype._create = function(){ - var frame = document.createElement('div'); - frame.className = 'itemset'; - frame['timeline-itemset'] = this; - this.dom.frame = frame; + var PointerEvent = Hammer.PointerEvent = { + /** + * holds all pointers, by `identifier` + * @property pointers + * @type {Object} + */ + pointers: {}, - // create background panel - var background = document.createElement('div'); - background.className = 'background'; - frame.appendChild(background); - this.dom.background = background; + /** + * 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; + }, - // create foreground panel - var foreground = document.createElement('div'); - foreground.className = 'foreground'; - frame.appendChild(foreground); - this.dom.foreground = foreground; + /** + * 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; + } + }, - // create axis panel - var axis = document.createElement('div'); - axis.className = 'axis'; - this.dom.axis = axis; + /** + * 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; + } - // create labelset - var labelSet = document.createElement('div'); - labelSet.className = 'labelset'; - this.dom.labelSet = labelSet; + var pt = ev.pointerType, + types = {}; - // create ungrouped Group - this._updateUngrouped(); + 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]; + }, - // create background Group - var backgroundGroup = new BackgroundGroup(BACKGROUND, null, this); - backgroundGroup.show(); - this.groups[BACKGROUND] = backgroundGroup; + /** + * reset the stored pointers + * @method reset + */ + reset: function resetList() { + this.pointers = {}; + } + }; - // 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, { - preventDefault: 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)); + /** + * @module hammer + * + * @class Detection + * @static + */ + var Detection = Hammer.detection = { + // contains all registred Hammer.gestures in the correct order + gestures: [], - // single select (or unselect) when tapping an item - this.hammer.on('tap', this._onSelectItem.bind(this)); + // data of the current Hammer.gesture detection session + current: null, - // multi select when holding mouse/touch, or on ctrl+click - this.hammer.on('hold', this._onMultiSelectItem.bind(this)); + // the previous Hammer.gesture session data + // is a full clone of the previous gesture.current object + previous: null, - // add item on doubletap - this.hammer.on('doubletap', this._onAddItem.bind(this)); + // when this becomes true, no gestures are fired + stopped: false, - // attach to the DOM - this.show(); - }; + /** + * 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; + } - /** - * 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', 'range', or 'background'. - * The default style can be overwritten by - * individual items. - * {String} align - * Alignment for the items, only applicable for - * BoxItem. 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', 'dataAttributes', 'template','hide', 'snap']; - util.selectiveExtend(fields, this.options, options); + this.stopped = false; - 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); - } - } - } - } + // 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 + }; - 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); - } - } + this.detect(eventData); + }, - // callback functions - var addCallback = (function (name) { - var fn = options[name]; - if (fn) { - if (!(fn instanceof Function)) { - throw new Error('option ' + name + ' must be a function ' + name + '(item, callback)'); + /** + * Hammer.gesture detection + * @method detect + * @param {Object} eventData + * @return {any} + */ + detect: function detect(eventData) { + if(!this.current || this.stopped) { + return; } - this.options[name] = fn; - } - }).bind(this); - ['onAdd', 'onUpdate', 'onRemove', 'onMove', 'onMoving'].forEach(addCallback); - // force the itemSet to refresh: options like orientation and margins may be changed - this.markDirty(); - } - }; + // extend event data with calculations about scale, distance etc + eventData = this.extendEventData(eventData); - /** - * Mark the ItemSet dirty so it will refresh everything with next redraw. - * Optionally, all items can be marked as dirty and be refreshed. - * @param {{refreshItems: boolean}} [options] - */ - ItemSet.prototype.markDirty = function(options) { - this.groupIds = []; - this.stackDirty = true; + // hammer instance and instance options + var inst = this.current.inst, + instOptions = inst.options; - if (options && options.refreshItems) { - util.forEach(this.items, function (item) { - item.dirty = true; - if (item.displayed) item.redraw(); - }); - } - }; + // 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); - /** - * Destroy the ItemSet - */ - ItemSet.prototype.destroy = function() { - this.hide(); - this.setItems(null); - this.setGroups(null); + // store as previous event event + if(this.current) { + this.current.lastEvent = eventData; + } - this.hammer = null; + if(eventData.eventType == EVENT_END) { + this.stopDetect(); + } - this.body = null; - this.conversion = null; - }; + return eventData; + }, - /** - * 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); - } + /** + * 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); - // remove the axis with dots - if (this.dom.axis.parentNode) { - this.dom.axis.parentNode.removeChild(this.dom.axis); - } + // reset the current + this.current = null; + this.stopped = true; + }, - // remove the labelset containing all group labels - if (this.dom.labelSet.parentNode) { - this.dom.labelSet.parentNode.removeChild(this.dom.labelSet); - } - }; + /** + * 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; - /** - * 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); - } + 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; + } - // show axis with dots - if (!this.dom.axis.parentNode) { - this.body.dom.backgroundVertical.appendChild(this.dom.axis); - } + if(ev.eventType == EVENT_TOUCH || ev.eventType == EVENT_RELEASE) { + cur.futureCalcEvent = ev; + } - // show labelset containing labels - if (!this.dom.labelSet.parentNode) { - this.body.dom.left.appendChild(this.dom.labelSet); - } - }; + 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); - /** - * Set selected items by their id. Replaces the current selection - * Unknown id's are silently ignored. - * @param {string[] | string} [ids] An array with zero or more id's of the items to be - * selected, or a single item id. If ids is undefined - * or an empty array, all items will be unselected. - */ - ItemSet.prototype.setSelection = function(ids) { - var i, ii, id, item; + cur.lastCalcEvent = cur.futureCalcEvent || ev; + cur.futureCalcEvent = ev; + } - if (ids == undefined) ids = []; - if (!Array.isArray(ids)) ids = [ids]; + ev.velocityX = calcData.velocity.x; + ev.velocityY = calcData.velocity.y; + ev.interimAngle = calcData.angle; + ev.interimDirection = calcData.direction; + }, - // 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(); - } + /** + * 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; - // 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(); - } - } - }; + // 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 + }); + }); + } - /** - * Get the selected items by their id - * @return {Array} ids The ids of the selected items - */ - ItemSet.prototype.getSelection = function() { - return this.selection.concat([]); - }; + var deltaTime = ev.timeStamp - startEv.timeStamp, + deltaX = ev.center.clientX - startEv.center.clientX, + deltaY = ev.center.clientY - startEv.center.clientY; - /** - * 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); + this.getCalculatedData(ev, lastEv.center, deltaTime, deltaX, deltaY); - var ids = []; - for (var groupId in this.groups) { - if (this.groups.hasOwnProperty(groupId)) { - var group = this.groups[groupId]; - var rawVisibleItems = group.visibleItems; + Utils.extend(ev, { + startEvent: startEv, - // 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); - } - } - } - } + deltaTime: deltaTime, + deltaX: deltaX, + deltaY: deltaY, - return ids; - }; + 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) + }); - /** - * 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; - } - } - }; - - /** - * 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; - - // recalculate absolute position (before redrawing groups) - this.props.top = this.body.domProps.top.height + this.body.domProps.border.top; - this.props.left = this.body.domProps.left.width + this.body.domProps.border.left; - - // update class name - frame.className = 'itemset' + (editable ? ' editable' : ''); - - // reorder the groups (if needed) - resized = this._orderGroups() || resized; - - // 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 restack = this.stackDirty; - var firstGroup = this._firstGroup(); - var firstMargin = { - item: margin.item, - axis: margin.axis - }; - var nonFirstMargin = { - item: margin.item, - axis: margin.item.vertical / 2 - }; - var height = 0; - var minHeight = margin.axis + margin.item.vertical; - - // redraw the background group - this.groups[BACKGROUND].redraw(range, nonFirstMargin, restack); + return ev; + }, - // redraw all regular groups - 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; + /** + * 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; + } - // update frame height - frame.style.height = asSize(height); + // extend Hammer default options with the Hammer.gesture options + Utils.extend(Hammer.defaults, options, true); - // calculate actual size - this.props.width = frame.offsetWidth; - this.props.height = height; + // set its index + gesture.index = gesture.index || 1000; - // 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 = '0'; + // add Hammer.gesture to the list + this.gestures.push(gesture); - // check if this component is resized - resized = this._isResized() || resized; + // 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 resized; + return this.gestures; + } }; + /** - * Get the first group, aligned with the axis - * @return {Group | null} firstGroup - * @private + * @module hammer */ - 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; - }; /** - * Create or delete the group holding all ungrouped items. This group is used when - * there are no groups specified. - * @protected + * 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} */ - ItemSet.prototype._updateUngrouped = function() { - var ungrouped = this.groups[UNGROUPED]; - var background = this.groups[BACKGROUND]; - var item, itemId; - - if (this.groupsData) { - // remove the group holding all ungrouped items - if (ungrouped) { - ungrouped.hide(); - delete this.groups[UNGROUPED]; + Hammer.Instance = function(element, options) { + var self = this; - for (itemId in this.items) { - if (this.items.hasOwnProperty(itemId)) { - item = this.items[itemId]; - item.parent && item.parent.remove(item); - var groupId = this._getGroupId(item.data); - var group = this.groups[groupId]; - group && group.add(item) || item.hide(); - } - } - } - } - 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; + // setup HammerJS window events and register all gestures + // this also sets up the default options + setup(); - for (itemId in this.items) { - if (this.items.hasOwnProperty(itemId)) { - item = this.items[itemId]; - ungrouped.add(item); - } - } + /** + * @property element + * @type {HTMLElement} + */ + this.element = element; - ungrouped.show(); - } - } - }; + /** + * @property enabled + * @type {Boolean} + * @protected + */ + this.enabled = true; - /** - * Get the element for the labelset - * @return {HTMLElement} labelSet - */ - ItemSet.prototype.getLabelSet = function() { - return this.dom.labelSet; - }; + /** + * options, merged with the defaults + * options with an _ are converted to camelCase + * @property options + * @type {Object} + */ + Utils.each(options, function(value, name) { + delete options[name]; + options[Utils.toCamelCase(name)] = value; + }); - /** - * Set items - * @param {vis.DataSet | null} items - */ - ItemSet.prototype.setItems = function(items) { - var me = this, - ids, - oldItemsData = this.itemsData; + this.options = Utils.extend(Utils.extend({}, Hammer.defaults), options || {}); - // 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'); - } + // 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); + } - if (oldItemsData) { - // unsubscribe from old dataset - util.forEach(this.itemListeners, function (callback, event) { - oldItemsData.off(event, callback); + /** + * 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 all drawn items - ids = oldItemsData.getIds(); - this._onRemove(ids); - } + /** + * keep a list of user event handlers which needs to be removed when calling 'dispose' + * @property eventHandlers + * @type {Array} + */ + this.eventHandlers = []; + }; - if (this.itemsData) { - // subscribe to new dataset - var id = this.id; - util.forEach(this.itemListeners, function (callback, event) { - me.itemsData.on(event, callback, id); - }); + Hammer.Instance.prototype = { + /** + * bind events to the instance + * @method on + * @chainable + * @param {String} gestures multiple gestures by splitting with a space + * @param {Function} handler + * @param {Object} handler.ev event object + */ + on: function onEvent(gestures, handler) { + var self = this; + Event.on(self.element, gestures, handler, function(type) { + self.eventHandlers.push({ gesture: type, handler: handler }); + }); + return self; + }, - // add all new items - ids = this.itemsData.getIds(); - this._onAdd(ids); + /** + * unbind events to the instance + * @method off + * @chainable + * @param {String} gestures + * @param {Function} handler + */ + off: function offEvent(gestures, handler) { + var self = this; - // update the group holding all ungrouped items - this._updateUngrouped(); - } - }; + 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; + }, - /** - * Get the current items - * @returns {vis.DataSet | null} - */ - ItemSet.prototype.getItems = function() { - return this.itemsData; - }; + /** + * trigger gesture event + * @method trigger + * @chainable + * @param {String} gesture + * @param {Object} [eventData] + */ + trigger: function triggerEvent(gesture, eventData) { + // optional + if(!eventData) { + eventData = {}; + } - /** - * Set groups - * @param {vis.DataSet} groups - */ - ItemSet.prototype.setGroups = function(groups) { - var me = this, - ids; + // create DOM event + var event = Hammer.DOCUMENT.createEvent('Event'); + event.initEvent(gesture, true, true); + event.gesture = eventData; - // unsubscribe from current dataset - if (this.groupsData) { - util.forEach(this.groupListeners, function (callback, event) { - me.groupsData.unsubscribe(event, callback); - }); + // 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; + } - // remove all drawn groups - ids = this.groupsData.getIds(); - this.groupsData = null; - this._onRemoveGroups(ids); // note: this will cause a redraw - } + element.dispatchEvent(event); + return this; + }, - // 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'); - } + /** + * enable of disable hammer.js detection + * @method enable + * @chainable + * @param {Boolean} state + */ + enable: function enable(state) { + this.enabled = state; + return this; + }, - if (this.groupsData) { - // subscribe to new dataset - var id = this.id; - util.forEach(this.groupListeners, function (callback, event) { - me.groupsData.on(event, callback, id); - }); + /** + * dispose this hammer instance + * @method dispose + * @return {Null} + */ + dispose: function dispose() { + var i, eh; - // draw all ms - ids = this.groupsData.getIds(); - this._onAddGroups(ids); - } + // undo all changes made by stop_browser_behavior + Utils.toggleBehavior(this.element, this.options.behavior, false); - // update the group holding all ungrouped items - this._updateUngrouped(); + // unbind all custom event handlers + for(i = -1; (eh = this.eventHandlers[++i]);) { + Utils.off(this.element, eh.gesture, eh.handler); + } - // update the order of all items in each group - this._order(); + this.eventHandlers = []; - this.body.emitter.emit('change', {queue: true}); + // unbind the start event listener + Event.off(this.element, EVENT_TYPES[EVENT_START], this.eventStartHandler); + + return null; + } }; + /** - * Get the current groups - * @returns {vis.DataSet | null} groups + * @module gestures */ - ItemSet.prototype.getGroups = function() { - return this.groupsData; - }; - /** - * Remove an item by its id - * @param {String | Number} id + * 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 */ - 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); - } - }); - } - }; - /** - * Get the time of an item based on it's data and options.type - * @param {Object} itemData - * @returns {string} Returns the type - * @private + * @event drag + * @param {Object} ev */ - ItemSet.prototype._getType = function (itemData) { - return itemData.type || this.options.type || (itemData.end ? 'range' : 'box'); - }; - - /** - * Get the group id for an item - * @param {Object} itemData - * @returns {string} Returns the groupId - * @private + * @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 */ - ItemSet.prototype._getGroupId = function (itemData) { - var type = this._getType(itemData); - if (type == 'background' && itemData.group == undefined) { - return BACKGROUND; - } - else { - return this.groupsData ? itemData.group : UNGROUPED; - } - }; /** - * Handle updated items - * @param {Number[]} ids - * @protected + * @param {String} name */ - ItemSet.prototype._onUpdate = function(ids) { - var me = this; + (function(name) { + var triggered = false; - ids.forEach(function (id) { - var itemData = me.itemsData.get(id, me.itemOptions); - var item = me.items[id]; - var type = me._getType(itemData); + function dragGesture(ev, inst) { + var cur = Detection.current; - var constructor = ItemSet.types[type]; + // max touches + if(inst.options.dragMaxTouches > 0 && + ev.touches.length > inst.options.dragMaxTouches) { + 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); - } - } - - 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 + '"'); - } - } - }); + switch(ev.eventType) { + case EVENT_START: + triggered = false; + break; - this._order(); - this.stackDirty = true; // force re-stacking of all items next redraw - this.body.emitter.emit('change', {queue: true}); - }; + 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; + } - /** - * Handle added items - * @param {Number[]} ids - * @protected - */ - ItemSet.prototype._onAdd = ItemSet.prototype._onUpdate; + var startCenter = cur.startEvent.center; - /** - * 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); - } - }); + // 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; - if (count) { - // update order - this._order(); - this.stackDirty = true; // force re-stacking of all items next redraw - this.body.emitter.emit('change', {queue: true}); - } - }; + // recalculate event data using new start point + ev = Detection.extendEventData(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(); - }); - }; + // lock drag to axis? + if(cur.lastEvent.dragLockToAxis || + ( inst.options.dragLockToAxis && + inst.options.dragLockMinDistance <= ev.distance + )) { + ev.dragLockToAxis = true; + } - /** - * Handle updated groups - * @param {Number[]} ids - * @private - */ - ItemSet.prototype._onUpdateGroups = function(ids) { - this._onAddGroups(ids); - }; + // 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; + } + } - /** - * Handle changed groups (added or updated) - * @param {Number[]} ids - * @private - */ - ItemSet.prototype._onAddGroups = function(ids) { - var me = this; + // first time, trigger dragstart event + if(!triggered) { + inst.trigger(name + 'start', ev); + triggered = true; + } - ids.forEach(function (id) { - var groupData = me.groupsData.get(id); - var group = me.groups[id]; + // trigger events + inst.trigger(name, ev); + inst.trigger(name + ev.direction, ev); - if (!group) { - // check for reserved ids - if (id == UNGROUPED || id == BACKGROUND) { - throw new Error('Illegal group id. ' + id + ' is a reserved id.'); - } + var isVertical = Utils.isVertical(ev.direction); - var groupOptions = Object.create(me.options); - util.extend(groupOptions, { - height: null - }); + // block the browser events + if((inst.options.dragBlockVertical && isVertical) || + (inst.options.dragBlockHorizontal && !isVertical)) { + ev.preventDefault(); + } + break; - group = new Group(id, groupData, me); - me.groups[id] = group; + case EVENT_RELEASE: + if(triggered && ev.changedLength <= inst.options.dragMaxTouches) { + inst.trigger(name + 'end', ev); + triggered = false; + } + 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); - } + case EVENT_END: + triggered = false; + break; } - } - - group.order(); - group.show(); - } - else { - // update group - group.setData(groupData); - } - }); - - this.body.emitter.emit('change', {queue: true}); - }; - - /** - * Handle removed groups - * @param {Number[]} ids - * @private - */ - ItemSet.prototype._onRemoveGroups = function(ids) { - var groups = this.groups; - ids.forEach(function (id) { - var group = groups[id]; - - if (group) { - group.hide(); - delete groups[id]; } - }); - this.markDirty(); + 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, - this.body.emitter.emit('change', {queue: true}); - }; + /** + * 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, - /** - * 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 - }); + /** + * set 0 for unlimited, but this can conflict with transform + * @property dragMaxTouches + * @type {Number} + * @default 1 + */ + dragMaxTouches: 1, - 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(); - }); + /** + * 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, - // show the groups again, attach them to the DOM in correct order - groupIds.forEach(function (groupId) { - groups[groupId].show(); - }); + /** + * same as `dragBlockHorizontal`, but for vertical movement + * @property dragBlockVertical + * @type {Boolean} + * @default false + */ + dragBlockVertical: false, - this.groupIds = groupIds; - } + /** + * 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, - return changed; - } - else { - return 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'); /** - * Add a new item - * @param {Item} item - * @private + * @module gestures */ - ItemSet.prototype._addItem = function(item) { - this.items[item.id] = item; - - // add to group - var groupId = this._getGroupId(item.data); - var group = this.groups[groupId]; - if (group) group.add(item); - }; - /** - * Update an existing item - * @param {Item} item - * @param {Object} itemData - * @private + * trigger a simple gesture event, so you can do anything in your handler. + * only usable if you know what your doing... + * + * @class Gesture + * @static */ - ItemSet.prototype._updateItem = function(item, itemData) { - var oldGroupId = item.data.group; - - // update the items data (will redraw the item when displayed) - item.setData(itemData); - - // update group - if (oldGroupId != item.data.group) { - var oldGroup = this.groups[oldGroupId]; - if (oldGroup) oldGroup.remove(item); - - var groupId = this._getGroupId(item.data); - var group = this.groups[groupId]; - if (group) group.add(item); - } - }; - /** - * 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 + * @event gesture + * @param {Object} ev */ - 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 - item.parent && item.parent.remove(item); + Hammer.gestures.Gesture = { + name: 'gesture', + index: 1337, + handler: function releaseGesture(ev, inst) { + inst.trigger(this.name, ev); + } }; /** - * Create an array containing all items being a range (having an end date) - * @param array - * @returns {Array} - * @private + * @module gestures */ - ItemSet.prototype._constructByEndArray = function(array) { - var endArray = []; - - for (var i = 0; i < array.length; i++) { - if (array[i] instanceof RangeItem) { - endArray.push(array[i]); - } - } - return endArray; - }; - /** - * Register the clicked item on touch, before dragStart is initiated. - * - * dragStart is initiated from a mousemove event, which can have left the item - * already resulting in an item == null + * Touch stays at the same place for x time * - * @param {Event} event - * @private + * @class Hold + * @static */ - ItemSet.prototype._onTouch = function (event) { - // store the touched item, used in _onDragStart - this.touchParams.item = ItemSet.itemFromTarget(event); - }; - /** - * Start dragging the selected events - * @param {Event} event - * @private + * @event hold + * @param {Object} ev */ - ItemSet.prototype._onDragStart = function (event) { - if (!this.options.editable.updateTime && !this.options.editable.updateGroup) { - return; - } - - var item = this.touchParams.item || null; - var me = this; - var props; - - if (item && item.selected) { - var dragLeftItem = event.target.dragLeftItem; - var dragRightItem = event.target.dragRightItem; - if (dragLeftItem) { - props = { - item: dragLeftItem, - initialX: event.gesture.center.clientX - }; + /** + * @param {String} name + */ + (function(name) { + var timer; - 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; - } + function holdGesture(ev, inst) { + var options = inst.options, + current = Detection.current; - this.touchParams.itemProps = [props]; - } - else if (dragRightItem) { - props = { - item: dragRightItem, - initialX: event.gesture.center.clientX - }; + switch(ev.eventType) { + case EVENT_START: + clearTimeout(timer); - 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; - } + // set the gesture so we can check in the timeout if it still is + current.name = name; - this.touchParams.itemProps = [props]; - } - else { - this.touchParams.itemProps = this.getSelection().map(function (id) { - var item = me.items[id]; - var props = { - item: item, - initialX: event.gesture.center.clientX - }; + // 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 (me.options.editable.updateTime) { - if ('start' in item.data) { - props.start = item.data.start.valueOf(); + case EVENT_MOVE: + if(ev.distance > options.holdThreshold) { + clearTimeout(timer); + } + break; - if ('end' in item.data) { - // we store a duration here in order not to change the width - // of the item when moving it. - props.duration = item.data.end.valueOf() - props.start; - } - } - } - if (me.options.editable.updateGroup) { - if ('group' in item.data) props.group = item.data.group; + case EVENT_RELEASE: + clearTimeout(timer); + break; } - - return props; - }); } - event.stopPropagation(); - } - }; + 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'); /** - * Drag selected items - * @param {Event} event - * @private + * @module gestures */ - ItemSet.prototype._onDrag = function (event) { - event.preventDefault(); - - if (this.touchParams.itemProps) { - var me = this; - var snap = this.options.snap || null; - var xOffset = this.body.dom.root.offsetLeft + this.body.domProps.left.width; - var scale = this.body.util.getScale(); - var step = this.body.util.getStep(); - - // move - this.touchParams.itemProps.forEach(function (props) { - var newProps = {}; - var current = me.body.util.toTime(event.gesture.center.clientX - xOffset); - var initial = me.body.util.toTime(props.initialX - xOffset); - var offset = current - initial; - - if ('start' in props) { - var start = new Date(props.start + offset); - newProps.start = snap ? snap(start, scale, step) : start; - } - - if ('end' in props) { - var end = new Date(props.end + offset); - newProps.end = snap ? snap(end, scale, step) : end; - } - else if ('duration' in props) { - newProps.end = new Date(newProps.start.valueOf() + props.duration); - } - - if ('group' in props) { - // drag from one group to another - var group = me.groupFromTarget(event); - newProps.group = group && group.groupId; - } - - // confirm moving the item - var itemData = util.extend({}, props.item.data, newProps); - me.options.onMoving(itemData, function (itemData) { - if (itemData) { - me._updateItemProps(props.item, itemData); + /** + * when a touch is being released from the page + * + * @class Release + * @static + */ + /** + * @event release + * @param {Object} ev + */ + Hammer.gestures.Release = { + name: 'release', + index: Infinity, + handler: function releaseGesture(ev, inst) { + if(ev.eventType == EVENT_RELEASE) { + inst.trigger(this.name, ev); } - }); - }); - - this.stackDirty = true; // force re-stacking of all items next redraw - this.body.emitter.emit('change'); - - event.stopPropagation(); - } + } }; /** - * Update an items properties - * @param {Item} item - * @param {Object} props Can contain properties start, end, and group. - * @private + * @module gestures */ - ItemSet.prototype._updateItemProps = function(item, props) { - // TODO: copy all properties from props to item? (also new ones) - if ('start' in props) item.data.start = props.start; - if ('end' in props) item.data.end = props.end; - if ('group' in props && item.data.group != props.group) { - this._moveToGroup(item, props.group) - } - }; - /** - * Move an item to another group - * @param {Item} item - * @param {String | Number} groupId - * @private + * 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 */ - ItemSet.prototype._moveToGroup = function(item, groupId) { - var group = this.groups[groupId]; - if (group && group.groupId != item.data.group) { - var oldGroup = item.parent; - oldGroup.remove(item); - oldGroup.order(); - group.add(item); - group.order(); - - item.data.group = group.groupId; - } - }; - /** - * End of dragging selected items - * @param {Event} event - * @private + * @event swipe + * @param {Object} ev */ - ItemSet.prototype._onDragEnd = function (event) { - event.preventDefault() + /** + * @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, - if (this.touchParams.itemProps) { - // prepare a change set for the changed items - var changes = [], - me = this, - dataset = this.itemsData.getDataSet(); + /** + * @property swipeMaxTouches + * @type {Number} + * @default 1 + */ + swipeMaxTouches: 1, - var itemProps = this.touchParams.itemProps ; - this.touchParams.itemProps = null; - itemProps.forEach(function (props) { - var id = props.item.id, - itemData = me.itemsData.get(id, me.itemOptions); + /** + * horizontal swipe velocity + * @property swipeVelocityX + * @type {Number} + * @default 0.6 + */ + swipeVelocityX: 0.6, - 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; - } + /** + * vertical swipe velocity + * @property swipeVelocityY + * @type {Number} + * @default 0.6 + */ + swipeVelocityY: 0.6 + }, - // 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 - me._updateItemProps(props.item, props); + handler: function swipeGesture(ev, inst) { + if(ev.eventType == EVENT_RELEASE) { + var touches = ev.touches.length, + options = inst.options; - me.stackDirty = true; // force re-stacking of all items next redraw - me.body.emitter.emit('change'); - } - }); - } - }); + // max touches + if(touches < options.swipeMinTouches || + touches > options.swipeMaxTouches) { + return; + } - // apply the changes to the data (if there are changes) - if (changes.length) { - dataset.update(changes); + // 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); + } + } } - - event.stopPropagation(); - } }; /** - * Handle selecting/deselecting an item when tapping it - * @param {Event} event - * @private + * @module gestures */ - ItemSet.prototype._onSelectItem = function (event) { - if (!this.options.selectable) return; - - var ctrlKey = event.gesture.srcEvent && event.gesture.srcEvent.ctrlKey; - var shiftKey = event.gesture.srcEvent && event.gesture.srcEvent.shiftKey; - if (ctrlKey || shiftKey) { - this._onMultiSelectItem(event); - return; - } - - var oldSelection = this.getSelection(); - - 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: newSelection - }); - } - }; - /** - * Handle creation and updates of an item on double tap - * @param event - * @private + * Single tap and a double tap on a place + * + * @class Tap + * @static + */ + /** + * @event tap + * @param {Object} ev + */ + /** + * @event doubletap + * @param {Object} ev */ - ItemSet.prototype._onAddItem = function (event) { - if (!this.options.selectable) return; - if (!this.options.editable.add) return; - var me = this, - snap = this.options.snap || null, - item = ItemSet.itemFromTarget(event); + /** + * @param {String} name + */ + (function(name) { + var hasMoved = false; - if (item) { - // update item + function tapGesture(ev, inst) { + var options = inst.options, + current = Detection.current, + prev = Detection.previous, + sincePrev, + didDoubleTap; - // 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.getDataSet().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 scale = this.body.util.getScale(); - var step = this.body.util.getStep(); + switch(ev.eventType) { + case EVENT_START: + hasMoved = false; + break; - var newItem = { - start: snap ? snap(start, scale, step) : start, - content: 'new item' - }; + case EVENT_MOVE: + hasMoved = hasMoved || (ev.distance > options.tapMaxDistance); + break; - // when default type is a range, add a default end date to the new item - if (this.options.type === 'range') { - var end = this.body.util.toTime(x + this.props.width / 5); - newItem.end = snap ? snap(end, scale, step) : end; - } + 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; - newItem[this.itemsData._fieldId] = util.randomUUID(); + // check if double tap + if(prev && prev.name == name && + (sincePrev && sincePrev < options.doubleTapInterval) && + ev.distance < options.doubleTapDistance) { + inst.trigger('doubletap', ev); + didDoubleTap = true; + } - var group = this.groupFromTarget(event); - if (group) { - newItem.group = group.groupId; + // do a single tap + if(!didDoubleTap || options.tapAlways) { + current.name = name; + inst.trigger(current.name, ev); + } + } + break; + } } - // execute async handler to customize (or cancel) adding an item - this.options.onAdd(newItem, function (item) { - if (item) { - me.itemsData.getDataSet().add(item); - // TODO: need to trigger a redraw? - } - }); - } - }; - - /** - * Handle selecting/deselecting multiple items when holding an item - * @param {Event} event - * @private - */ - ItemSet.prototype._onMultiSelectItem = function (event) { - if (!this.options.selectable) return; + 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, - var selection, - item = ItemSet.itemFromTarget(event); + /** + * max distance of movement of a tap, this is for the slow tappers + * @property tapMaxDistance + * @type {Number} + * @default 10 + */ + tapMaxDistance: 10, - if (item) { - // multi select items - selection = this.getSelection(); // current selection + /** + * always trigger the `tap` event, even while double-tapping + * @property tapAlways + * @type {Boolean} + * @default true + */ + tapAlways: true, - var shiftKey = event.gesture.touches[0] && event.gesture.touches[0].shiftKey || false; - if (shiftKey) { - // select all items between the old selection and the tapped item + /** + * max distance between two taps + * @property doubleTapDistance + * @type {Number} + * @default 20 + */ + doubleTapDistance: 20, - // determine the selection range - selection.push(item.id); - var range = ItemSet._getItemRange(this.itemsData.get(selection, this.itemOptions)); + /** + * max time between two taps + * @property doubleTapInterval + * @type {Number} + * @default 300 + */ + doubleTapInterval: 300 + } + }; + })('tap'); - // select all items within the selection range - selection = []; - for (var id in this.items) { - if (this.items.hasOwnProperty(id)) { - var _item = this.items[id]; - var start = _item.data.start; - var end = (_item.data.end !== undefined) ? _item.data.end : start; + /** + * @module gestures + */ + /** + * when a touch is being touched at the page + * + * @class Touch + * @static + */ + /** + * @event touch + * @param {Object} ev + */ + Hammer.gestures.Touch = { + name: 'touch', + index: -Infinity, + defaults: { + /** + * call preventDefault at touchstart, and makes the element blocking by disabling the scrolling of the page, + * but it improves gestures like transforming and dragging. + * be careful with using this, it can be very annoying for users to be stuck on the page + * @property preventDefault + * @type {Boolean} + * @default false + */ + preventDefault: false, - if (start >= range.min && end <= range.max) { - selection.push(_item.id); // do not use id but item.id, id itself is stringified - } + /** + * 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; } - } - } - else { - // add/remove this item from the current selection - var index = selection.indexOf(item.id); - if (index == -1) { - // item is not yet selected -> select it - selection.push(item.id); - } - else { - // item is already selected -> deselect it - selection.splice(index, 1); - } - } - this.setSelection(selection); + if(inst.options.preventDefault) { + ev.preventDefault(); + } - this.body.emitter.emit('select', { - items: this.getSelection() - }); - } + if(ev.eventType == EVENT_TOUCH) { + inst.trigger('touch', ev); + } + } }; /** - * Calculate the time range of a list of items - * @param {Array.} itemsData - * @return {{min: Date, max: Date}} Returns the range of the provided items - * @private + * @module gestures */ - ItemSet._getItemRange = function(itemsData) { - var max = null; - var min = null; - - itemsData.forEach(function (data) { - if (min == null || data.start < min) { - min = data.start; - } - - if (data.end != undefined) { - if (max == null || data.end > max) { - max = data.end; - } - } - else { - if (max == null || data.start > max) { - max = data.start; - } - } - }); - - return { - min: min, - max: max - } - }; - /** - * 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 + * User want to scale or rotate with 2 fingers + * Preventing the default browser behavior is a good way to improve feel and working. This can be done with the + * `preventDefault` option. + * + * @class Transform + * @static + */ + /** + * @event transform + * @param {Object} ev + */ + /** + * @event transformstart + * @param {Object} ev + */ + /** + * @event transformend + * @param {Object} ev + */ + /** + * @event pinchin + * @param {Object} ev + */ + /** + * @event pinchout + * @param {Object} ev + */ + /** + * @event rotate + * @param {Object} ev */ - ItemSet.itemFromTarget = function(event) { - var target = event.target; - while (target) { - if (target.hasOwnProperty('timeline-item')) { - return target['timeline-item']; - } - target = target.parentNode; - } - - return null; - }; /** - * Find the Group from an event target: - * searches for the attribute 'timeline-group' in the event target's element tree - * @param {Event} event - * @return {Group | null} group + * @param {String} name */ - ItemSet.prototype.groupFromTarget = function(event) { - // TODO: cleanup when the new solution is stable (also on mobile) - //var target = event.target; - //while (target) { - // if (target.hasOwnProperty('timeline-group')) { - // return target['timeline-group']; - // } - // target = target.parentNode; - //} - // + (function(name) { + var triggered = false; - var clientY = event.gesture.center.clientY; - for (var i = 0; i < this.groupIds.length; i++) { - var groupId = this.groupIds[i]; - var group = this.groups[groupId]; - var foreground = group.dom.foreground; - var top = util.getAbsoluteTop(foreground); - if (clientY > top && clientY < top + foreground.offsetHeight) { - return group; - } + function transformGesture(ev, inst) { + switch(ev.eventType) { + case EVENT_START: + triggered = false; + break; - if (this.options.orientation === 'top') { - if (i === this.groupIds.length - 1 && clientY > top) { - return group; - } - } - else { - if (i === 0 && clientY < top + foreground.offset) { - return group; - } + 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; + + // 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); + } + + // trigger pinch event + if(scaleThreshold > inst.options.transformMinScale) { + inst.trigger('pinch', ev); + inst.trigger('pinch' + (ev.scale < 1 ? 'in' : 'out'), ev); + } + break; + + case EVENT_RELEASE: + if(triggered && ev.changedLength < 2) { + inst.trigger(name + 'end', ev); + triggered = false; + } + break; + } } - } - return null; - }; + 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'); /** - * 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 + * @module hammer */ - ItemSet.itemSetFromTarget = function(event) { - var target = event.target; - while (target) { - if (target.hasOwnProperty('timeline-itemset')) { - return target['timeline-itemset']; - } - target = target.parentNode; - } - return null; - }; - - module.exports = ItemSet; + // AMD export + if(true) { + !(__WEBPACK_AMD_DEFINE_RESULT__ = function() { + return Hammer; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + // commonjs export + } else if(typeof module !== 'undefined' && module.exports) { + module.exports = Hammer; + // browser export + } else { + window.Hammer = Hammer; + } + })(window); /***/ }, -/* 28 */ +/* 21 */ /***/ function(module, exports, __webpack_require__) { var util = __webpack_require__(1); - var DOMutil = __webpack_require__(2); - var Component = __webpack_require__(20); + var hammerUtil = __webpack_require__(22); + var moment = __webpack_require__(2); + var Component = __webpack_require__(23); + var DateUtil = __webpack_require__(24); /** - * Legend for Graph2d + * @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 Legend(body, options, side, linegraphOptions) { + function Range(body, options) { + var now = moment().hours(0).minutes(0).seconds(0).milliseconds(0); + this.start = now.clone().add(-3, 'days').valueOf(); // Number + this.end = now.clone().add(4, 'days').valueOf(); // Number + this.body = body; + this.deltaDifference = 0; + this.scaleOffset = 0; + this.startToFront = false; + this.endToFront = true; + + // default options 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.linegraphOptions = linegraphOptions; + 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); - this.svgElements = {}; - this.dom = {}; - this.groups = {}; - this.amountOfGroups = 0; - this._create(); + this.props = { + touch: {} + }; + this.animateTimer = null; - this.setOptions(options); - } + // 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)); - Legend.prototype = new Component(); + // ignore dragging when holding + this.body.emitter.on('hold', this._onHold.bind(this)); - Legend.prototype.clear = function() { - this.groups = {}; - this.amountOfGroups = 0; + // mouse wheel for zooming + this.body.emitter.on('mousewheel', this._onMouseWheel.bind(this)); + this.body.emitter.on('DOMMouseScroll', this._onMouseWheel.bind(this)); // For FF + + // pinch to zoom + this.body.emitter.on('touch', this._onTouch.bind(this)); + this.body.emitter.on('pinch', this._onPinch.bind(this)); + + this.setOptions(options); } - Legend.prototype.addGroup = function(label, graphOptions) { + Range.prototype = new Component(); - if (!this.groups.hasOwnProperty(label)) { - this.groups[label] = graphOptions; + /** + * 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 + */ + Range.prototype.setOptions = function (options) { + if (options) { + // copy the options that we know + var fields = ['direction', 'min', 'max', 'zoomMin', 'zoomMax', 'moveable', 'zoomable', 'activate', 'hiddenDates']; + util.selectiveExtend(fields, this.options, options); + + if ('start' in options || 'end' in options) { + // apply a new range. both start and end are optional + this.setRange(options.start, options.end); + } } - this.amountOfGroups += 1; }; - Legend.prototype.updateGroup = function(label, graphOptions) { - this.groups[label] = graphOptions; - }; + /** + * 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".'); + } + } - Legend.prototype.removeGroup = function(label) { - if (this.groups.hasOwnProperty(label)) { - delete this.groups[label]; - this.amountOfGroups -= 1; + /** + * Set a new start and end range + * @param {Date | Number | String} [start] + * @param {Date | Number | String} [end] + * @param {boolean | number} [animate=false] If true, the range is animated + * smoothly to the new window. + * If animate is a number, the + * number is taken as duration + * Default duration is 500 ms. + * @param {Boolean} [byUser=false] + * + */ + Range.prototype.setRange = function(start, end, animate, byUser) { + if (byUser !== true) { + byUser = false; } - }; + var _start = start != undefined ? util.convert(start, 'Date').valueOf() : null; + var _end = end != undefined ? util.convert(end, 'Date').valueOf() : null; + this._cancelAnimation(); - 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"; + if (animate) { + var me = this; + var initStart = this.start; + var initEnd = this.end; + var duration = typeof animate === 'number' ? animate : 500; + var initTime = new Date().valueOf(); + var anyChanged = false; - this.dom.textArea = document.createElement('div'); - this.dom.textArea.className = 'legendText'; - this.dom.textArea.style.position = "relative"; - this.dom.textArea.style.top = "0px"; + var next = function () { + if (!me.props.touch.dragging) { + var now = new Date().valueOf(); + var time = now - initTime; + var done = time > duration; + var s = (done || _start === null) ? _start : util.easeInOutQuad(time, initStart, _start, duration); + var e = (done || _end === null) ? _end : util.easeInOutQuad(time, initEnd, _end, duration); - this.svg = document.createElementNS('http://www.w3.org/2000/svg',"svg"); - this.svg.style.position = 'absolute'; - this.svg.style.top = 0 +'px'; - this.svg.style.width = this.options.iconSize + 5 + 'px'; - this.svg.style.height = '100%'; + changed = me._applyRange(s, e); + DateUtil.updateHiddenDates(me.body, me.options.hiddenDates); + anyChanged = anyChanged || changed; + if (changed) { + me.body.emitter.emit('rangechange', {start: new Date(me.start), end: new Date(me.end), byUser:byUser}); + } - this.dom.frame.appendChild(this.svg); - this.dom.frame.appendChild(this.dom.textArea); + if (done) { + if (anyChanged) { + me.body.emitter.emit('rangechanged', {start: new Date(me.start), end: new Date(me.end), byUser:byUser}); + } + } + else { + // animate with as high as possible frame rate, leave 20 ms in between + // each to prevent the browser from blocking + me.animateTimer = setTimeout(next, 20); + } + } + }; + + return next(); + } + else { + var changed = this._applyRange(_start, _end); + DateUtil.updateHiddenDates(this.body, this.options.hiddenDates); + if (changed) { + var params = {start: new Date(this.start), end: new Date(this.end), byUser:byUser}; + this.body.emitter.emit('rangechange', params); + this.body.emitter.emit('rangechanged', params); + } + } }; /** - * Hide the component from the DOM + * Stop an animation + * @private */ - Legend.prototype.hide = function() { - // remove the frame containing the items - if (this.dom.frame.parentNode) { - this.dom.frame.parentNode.removeChild(this.dom.frame); + Range.prototype._cancelAnimation = function () { + if (this.animateTimer) { + clearTimeout(this.animateTimer); + this.animateTimer = null; } }; /** - * Show the component in the DOM (when not already visible). + * 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 */ - Legend.prototype.show = function() { - // show frame containing the items - if (!this.dom.frame.parentNode) { - this.body.dom.center.appendChild(this.dom.frame); + 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 + '"'); } - }; - Legend.prototype.setOptions = function(options) { - var fields = ['enabled','orientation','icons','left','right']; - util.selectiveDeepExtend(fields, this.options, options); - }; + // prevent start < end + if (newEnd < newStart) { + newEnd = newStart; + } - Legend.prototype.redraw = function() { - var activeGroups = 0; - for (var groupId in this.groups) { - if (this.groups.hasOwnProperty(groupId)) { - if (this.groups[groupId].visible == true && (this.linegraphOptions.visibility[groupId] === undefined || this.linegraphOptions.visibility[groupId] == true)) { - activeGroups++; + // prevent start < min + if (min !== null) { + if (newStart < min) { + diff = (min - newStart); + newStart += diff; + newEnd += diff; + + // prevent end > max + if (max != null) { + if (newEnd > max) { + newEnd = max; + } } } } - 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 = ''; - } + // prevent end > max + if (max !== null) { + if (newEnd > max) { + diff = (newEnd - max); + newStart -= diff; + newEnd -= diff; - 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 { - var scrollableHeight = this.body.domProps.center.height - this.body.domProps.centerContainer.height; - this.dom.frame.style.bottom = 4 + scrollableHeight + Number(this.body.dom.center.style.top.replace("px","")) + 'px'; - this.dom.frame.style.top = ''; + // prevent start < min + if (min != null) { + if (newStart < min) { + newStart = min; + } + } } + } - 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'; + // prevent (end-start) < zoomMin + if (this.options.zoomMin !== null) { + var zoomMin = parseFloat(this.options.zoomMin); + if (zoomMin < 0) { + zoomMin = 0; } - else { - this.dom.frame.style.width = this.options.iconSize + 15 + this.dom.textArea.offsetWidth + 10 + 'px' - this.drawLegendIcons(); + if ((newEnd - newStart) < zoomMin) { + if ((this.end - this.start) === zoomMin && newStart > this.start && newEnd < this.end) { + // 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; + } } + } - var content = ''; - for (var groupId in this.groups) { - if (this.groups.hasOwnProperty(groupId)) { - if (this.groups[groupId].visible == true && (this.linegraphOptions.visibility[groupId] === undefined || this.linegraphOptions.visibility[groupId] == true)) { - content += this.groups[groupId].content + '
'; - } + // 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 && newStart < this.start && newEnd > this.end) { + // 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; } } - this.dom.textArea.innerHTML = content; - this.dom.textArea.style.lineHeight = ((0.75 * this.options.iconSize) + this.options.iconSpacing) + 'px'; } + + var changed = (this.start != newStart || this.end != newEnd); + + // if the new range does NOT overlap with the old range, emit checkRangedItems to avoid not showing ranged items (ranged meaning has end time, not necessarily of type Range) + if (!((newStart >= this.start && newStart <= this.end) || (newEnd >= this.start && newEnd <= this.end)) && + !((this.start >= newStart && this.start <= newEnd) || (this.end >= newStart && this.end <= newEnd) )) { + this.body.emitter.emit('checkRangedItems'); + } + + this.start = newStart; + this.end = newEnd; + return changed; }; - 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; + /** + * Retrieve the current range. + * @return {Object} An object with start and end properties + */ + Range.prototype.getRange = function() { + return { + start: this.start, + end: this.end + }; + }; - this.svg.style.width = iconWidth + 5 + iconOffset + 'px'; + /** + * Calculate the conversion offset and scale for current range, based on + * the provided width + * @param {Number} width + * @returns {{offset: number, scale: number}} conversion + */ + Range.prototype.conversion = function (width, totalHidden) { + return Range.conversion(this.start, this.end, width, totalHidden); + }; - for (var groupId in this.groups) { - if (this.groups.hasOwnProperty(groupId)) { - if (this.groups[groupId].visible == true && (this.linegraphOptions.visibility[groupId] === undefined || this.linegraphOptions.visibility[groupId] == true)) { - this.groups[groupId].drawIcon(x, y, this.svgElements, this.svg, iconWidth, iconHeight); - y += iconHeight + this.options.iconSpacing; - } - } + /** + * Static method to calculate the conversion offset and scale for a range, + * based on the provided start, end, and width + * @param {Number} start + * @param {Number} end + * @param {Number} width + * @returns {{offset: number, scale: number}} conversion + */ + Range.conversion = function (start, end, width, totalHidden) { + if (totalHidden === undefined) { + totalHidden = 0; + } + if (width != 0 && (end - start != 0)) { + return { + offset: start, + scale: width / (end - start - totalHidden) } - - DOMutil.cleanupElements(this.svgElements); + } + else { + return { + offset: 0, + scale: 1 + }; } }; - module.exports = Legend; - + /** + * Start dragging horizontally or vertically + * @param {Event} event + * @private + */ + Range.prototype._onDragStart = function(event) { + this.deltaDifference = 0; + this.previousDelta = 0; + // only allow dragging when configured as movable + if (!this.options.moveable) return; -/***/ }, -/* 29 */ -/***/ function(module, exports, __webpack_require__) { + // 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 util = __webpack_require__(1); - var DOMutil = __webpack_require__(2); - var DataSet = __webpack_require__(3); - var DataView = __webpack_require__(4); - var Component = __webpack_require__(20); - var DataAxis = __webpack_require__(23); - var GraphGroup = __webpack_require__(24); - var Legend = __webpack_require__(28); - var BarGraphFunctions = __webpack_require__(51); + this.props.touch.start = this.start; + this.props.touch.end = this.end; + this.props.touch.dragging = true; - var UNGROUPED = '__ungrouped__'; // reserved group id for ungrouped items + if (this.body.dom.root) { + this.body.dom.root.style.cursor = 'move'; + } + }; /** - * This is the constructor of the LineGraph. It requires a Timeline body and options. - * - * @param body - * @param options - * @constructor + * Perform dragging operation + * @param {Event} event + * @private */ - function LineGraph(body, options) { - this.id = util.randomUUID(); - this.body = body; - - 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, - handleOverlap: 'overlap', - 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, - alignZeros: true, - customRange: { - left: {min:undefined, max:undefined}, - right: {min:undefined, max:undefined} - } - //, these options are not set by default, but this shows the format they will be in - //format: { - // left: {decimals: 2}, - // right: {decimals: 2} - //}, - //title: { - // left: { - // text: 'left', - // style: 'color:black;' - // }, - // right: { - // text: 'right', - // style: 'color:black;' - // } - //} - }, - 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 - } - }, - groups: { - visibility: {} - } - }; - - // options is shared by this ItemSet and all its items - this.options = util.extend({}, this.defaultOptions); - this.dom = {}; - this.props = {}; - this.hammer = null; - this.groups = {}; - this.abortedGraphUpdate = false; - this.updateSVGheight = false; - this.updateSVGheightOnResize = false; + Range.prototype._onDrag = function (event) { + // only allow dragging when configured as movable + if (!this.options.moveable) return; + // refuse to drag when we where pinching to prevent the timeline make a jump + // when releasing the fingers in opposite order from the touch screen + if (!this.props.touch.allowDragging) return; - var me = this; - this.itemsData = null; // DataSet - this.groupsData = null; // DataSet + var direction = this.options.direction; + validateDirection(direction); - // 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); - } - }; + var delta = (direction == 'horizontal') ? event.gesture.deltaX : event.gesture.deltaY; + delta -= this.deltaDifference; + var interval = (this.props.touch.end - this.props.touch.start); - // 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); - } - }; + // normalize dragging speed if cutout is in between. + var duration = DateUtil.getHiddenDurationBetween(this.body.hiddenDates, this.start, this.end); + interval -= duration; - 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 + var width = (direction == 'horizontal') ? this.body.domProps.center.width : this.body.domProps.center.height; + var diffRange = -delta / width * interval; + var newStart = this.props.touch.start + diffRange; + var newEnd = this.props.touch.end + diffRange; - this.svgElements = {}; - this.setOptions(options); - this.groupsUsingDefaultStyles = [0]; - this.COUNTER = 0; - this.body.emitter.on('rangechanged', function() { - me.lastStart = me.body.range.start; - me.svg.style.left = util.option.asSize(-me.props.width); - me.redraw.call(me,true); - }); - // create the HTML DOM - this._create(); - this.framework = {svg: this.svg, svgElements: this.svgElements, options: this.options, groups: this.groups}; - this.body.emitter.emit('change'); + // snapping times away from hidden zones + var safeStart = DateUtil.snapAwayFromHidden(this.body.hiddenDates, newStart, this.previousDelta-delta, true); + var safeEnd = DateUtil.snapAwayFromHidden(this.body.hiddenDates, newEnd, this.previousDelta-delta, true); + if (safeStart != newStart || safeEnd != newEnd) { + this.deltaDifference += delta; + this.props.touch.start = safeStart; + this.props.touch.end = safeEnd; + this._onDrag(event); + return; + } - } + this.previousDelta = delta; + this._applyRange(newStart, newEnd); - LineGraph.prototype = new Component(); + // fire a rangechange event + this.body.emitter.emit('rangechange', { + start: new Date(this.start), + end: new Date(this.end), + byUser: true + }); + }; /** - * Create the HTML DOM for the ItemSet + * Stop dragging operation + * @param {event} event + * @private */ - LineGraph.prototype._create = function(){ - var frame = document.createElement('div'); - frame.className = 'LineGraph'; - this.dom.frame = frame; - - // create svg element for graph drawing. - this.svg = document.createElementNS('http://www.w3.org/2000/svg','svg'); - this.svg.style.position = 'relative'; - this.svg.style.height = ('' + this.options.graphHeight).replace('px','') + 'px'; - this.svg.style.display = 'block'; - frame.appendChild(this.svg); - - // data axis - this.options.dataAxis.orientation = 'left'; - this.yAxisLeft = new DataAxis(this.body, this.options.dataAxis, this.svg, this.options.groups); + Range.prototype._onDragEnd = function (event) { + // only allow dragging when configured as movable + if (!this.options.moveable) return; - this.options.dataAxis.orientation = 'right'; - this.yAxisRight = new DataAxis(this.body, this.options.dataAxis, this.svg, this.options.groups); - delete this.options.dataAxis.orientation; + // 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; - // legends - this.legendLeft = new Legend(this.body, this.options.legend, 'left', this.options.groups); - this.legendRight = new Legend(this.body, this.options.legend, 'right', this.options.groups); + this.props.touch.dragging = false; + if (this.body.dom.root) { + this.body.dom.root.style.cursor = 'auto'; + } - this.show(); + // fire a rangechanged event + this.body.emitter.emit('rangechanged', { + start: new Date(this.start), + end: new Date(this.end), + byUser: true + }); }; /** - * set the options of the LineGraph. the mergeOptions is used for subObjects that have an enabled element. - * @param {object} options + * Event handler for mouse wheel event, used to zoom + * Code from http://adomas.org/javascript-mouse-wheel/ + * @param {Event} event + * @private */ - LineGraph.prototype.setOptions = function(options) { - if (options) { - var fields = ['sampling','defaultGroup','height','graphHeight','yAxisOrientation','style','barChart','dataAxis','sort','groups']; - if (options.graphHeight === undefined && options.height !== undefined && this.body.domProps.centerContainer.height !== undefined) { - this.updateSVGheight = true; - this.updateSVGheightOnResize = true; - } - else if (this.body.domProps.centerContainer.height !== undefined && options.graphHeight !== undefined) { - if (parseInt((options.graphHeight + '').replace("px",'')) < this.body.domProps.centerContainer.height) { - this.updateSVGheight = true; - } - } - 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'); + Range.prototype._onMouseWheel = function(event) { + // only allow zooming when configured as zoomable and moveable + if (!(this.options.zoomable && this.options.moveable)) return; - if (options.catmullRom) { - if (typeof options.catmullRom == 'object') { - if (options.catmullRom.parametrization) { - if (options.catmullRom.parametrization == 'uniform') { - this.options.catmullRom.alpha = 0; - } - else if (options.catmullRom.parametrization == 'chordal') { - this.options.catmullRom.alpha = 1.0; - } - else { - this.options.catmullRom.parametrization = 'centripetal'; - this.options.catmullRom.alpha = 0.5; - } - } - } - } + // 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 (this.yAxisLeft) { - if (options.dataAxis !== undefined) { - this.yAxisLeft.setOptions(this.options.dataAxis); - this.yAxisRight.setOptions(this.options.dataAxis); - } - } + // If delta is nonzero, handle it. + // Basically, delta is now positive if wheel was scrolled up, + // and negative, if wheel was scrolled down. + if (delta) { + // perform the zoom action. Delta is normally 1 or -1 - if (this.legendLeft) { - if (options.legend !== undefined) { - this.legendLeft.setOptions(this.options.legend); - this.legendRight.setOptions(this.options.legend); - } + // 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); } - - if (this.groups.hasOwnProperty(UNGROUPED)) { - this.groups[UNGROUPED].setOptions(options); + else { + scale = 1 / (1 + (delta / 5)) ; } - } - // this is used to redraw the graph if the visibility of the groups is changed. - if (this.dom.frame) { - this.redraw(true); + // calculate center, the date to zoom around + var gesture = hammerUtil.fakeGesture(this, event), + pointer = getPointer(gesture.center, this.body.dom.center), + pointerDate = this._pointerToDate(pointer); + + this.zoom(scale, pointerDate, delta); } + + // Prevent default actions caused by mouse wheel + // (else the page and timeline both zoom and scroll) + event.preventDefault(); }; /** - * Hide the component from the DOM + * Start of a touch gesture + * @private */ - LineGraph.prototype.hide = function() { - // remove the frame containing the items - if (this.dom.frame.parentNode) { - this.dom.frame.parentNode.removeChild(this.dom.frame); - } + 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; + this.scaleOffset = 0; + this.deltaDifference = 0; }; - /** - * Show the component in the DOM (when not already visible). - * @return {Boolean} changed + * On start of a hold gesture + * @private */ - LineGraph.prototype.show = function() { - // show frame containing the items - if (!this.dom.frame.parentNode) { - this.body.dom.center.appendChild(this.dom.frame); - } + Range.prototype._onHold = function () { + this.props.touch.allowDragging = false; }; - /** - * Set items - * @param {vis.DataSet | null} items + * Handle pinch event + * @param {Event} event + * @private */ - LineGraph.prototype.setItems = function(items) { - var me = this, - ids, - oldItemsData = this.itemsData; + Range.prototype._onPinch = function (event) { + // only allow zooming when configured as zoomable and moveable + if (!(this.options.zoomable && this.options.moveable)) return; - // 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'); - } + this.props.touch.allowDragging = false; - if (oldItemsData) { - // unsubscribe from old dataset - util.forEach(this.itemListeners, function (callback, event) { - oldItemsData.off(event, callback); - }); + if (event.gesture.touches.length > 1) { + if (!this.props.touch.center) { + this.props.touch.center = getPointer(event.gesture.center, this.body.dom.center); + } - // remove all drawn items - ids = oldItemsData.getIds(); - this._onRemove(ids); - } + var scale = 1 / (event.gesture.scale + this.scaleOffset); + var centerDate = this._pointerToDate(this.props.touch.center); - if (this.itemsData) { - // subscribe to new dataset - var id = this.id; - util.forEach(this.itemListeners, function (callback, event) { - me.itemsData.on(event, callback, id); - }); + var hiddenDuration = DateUtil.getHiddenDurationBetween(this.body.hiddenDates, this.start, this.end); + var hiddenDurationBefore = DateUtil.getHiddenDurationBefore(this.body.hiddenDates, this, centerDate); + var hiddenDurationAfter = hiddenDuration - hiddenDurationBefore; - // add all new items - ids = this.itemsData.getIds(); - this._onAdd(ids); + // calculate new start and end + var newStart = (centerDate - hiddenDurationBefore) + (this.props.touch.start - (centerDate - hiddenDurationBefore)) * scale; + var newEnd = (centerDate + hiddenDurationAfter) + (this.props.touch.end - (centerDate + hiddenDurationAfter)) * scale; + + // snapping times away from hidden zones + this.startToFront = 1 - scale > 0 ? false : true; // used to do the right autocorrection with periodic hidden times + this.endToFront = scale - 1 > 0 ? false : true; // used to do the right autocorrection with periodic hidden times + + var safeStart = DateUtil.snapAwayFromHidden(this.body.hiddenDates, newStart, 1 - scale, true); + var safeEnd = DateUtil.snapAwayFromHidden(this.body.hiddenDates, newEnd, scale - 1, true); + if (safeStart != newStart || safeEnd != newEnd) { + this.props.touch.start = safeStart; + this.props.touch.end = safeEnd; + this.scaleOffset = 1 - event.gesture.scale; + newStart = safeStart; + newEnd = safeEnd; + } + + this.setRange(newStart, newEnd, false, true); + + this.startToFront = false; // revert to default + this.endToFront = true; // revert to default } - this._updateUngrouped(); - //this._updateGraph(); - this.redraw(true); }; - /** - * Set groups - * @param {vis.DataSet} groups + * Helper function to calculate the center date for zooming + * @param {{x: Number, y: Number}} pointer + * @return {number} date + * @private */ - LineGraph.prototype.setGroups = function(groups) { - var me = this; - var ids; - - // unsubscribe from current dataset - if (this.groupsData) { - util.forEach(this.groupListeners, function (callback, event) { - me.groupsData.unsubscribe(event, callback); - }); + Range.prototype._pointerToDate = function (pointer) { + var conversion; + var direction = this.options.direction; - // remove all drawn groups - ids = this.groupsData.getIds(); - this.groupsData = null; - this._onRemoveGroups(ids); // note: this will cause a redraw - } + validateDirection(direction); - // replace the dataset - if (!groups) { - this.groupsData = null; - } - else if (groups instanceof DataSet || groups instanceof DataView) { - this.groupsData = groups; + if (direction == 'horizontal') { + return this.body.util.toTime(pointer.x).valueOf(); } 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); + var height = this.body.domProps.center.height; + conversion = this.conversion(height); + return pointer.y / conversion.scale + conversion.offset; } - this._onUpdate(); }; - /** - * Update the data - * @param [ids] + * 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 */ - LineGraph.prototype._onUpdate = function(ids) { - this._updateUngrouped(); - this._updateAllGroupData(); - //this._updateGraph(); - this.redraw(true); - }; - 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]); + function getPointer (touch, element) { + return { + x: touch.pageX - util.getAbsoluteLeft(element), + y: touch.pageY - util.getAbsoluteTop(element) + }; + } + + /** + * Zoom the range the given scale in or out. Start and end date will + * be adjusted, and the timeline will be redrawn. You can optionally give a + * date around which to zoom. + * For example, try scale = 0.9 or 1.1 + * @param {Number} scale Scaling factor. Values above 1 will zoom out, + * values below 1 will zoom in. + * @param {Number} [center] Value representing a date around which will + * be zoomed. + */ + Range.prototype.zoom = function(scale, center, delta) { + // if centerDate is not provided, take it half between start Date and end Date + if (center == null) { + center = (this.start + this.end) / 2; } - //this._updateGraph(); - this.redraw(true); - }; - LineGraph.prototype._onAddGroups = function (groupIds) {this._onUpdateGroups(groupIds);}; + var hiddenDuration = DateUtil.getHiddenDurationBetween(this.body.hiddenDates, this.start, this.end); + var hiddenDurationBefore = DateUtil.getHiddenDurationBefore(this.body.hiddenDates, this, center); + var hiddenDurationAfter = hiddenDuration - hiddenDurationBefore; + // calculate new start and end + var newStart = (center-hiddenDurationBefore) + (this.start - (center-hiddenDurationBefore)) * scale; + var newEnd = (center+hiddenDurationAfter) + (this.end - (center+hiddenDurationAfter)) * scale; - /** - * this cleans the group out off the legends and the dataaxis, updates the ungrouped and updates the graph - * @param {Array} groupIds - * @private - */ - 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]]; - } + // snapping times away from hidden zones + this.startToFront = delta > 0 ? false : true; // used to do the right autocorrection with periodic hidden times + this.endToFront = -delta > 0 ? false : true; // used to do the right autocorrection with periodic hidden times + var safeStart = DateUtil.snapAwayFromHidden(this.body.hiddenDates, newStart, delta, true); + var safeEnd = DateUtil.snapAwayFromHidden(this.body.hiddenDates, newEnd, -delta, true); + if (safeStart != newStart || safeEnd != newEnd) { + newStart = safeStart; + newEnd = safeEnd; } - this._updateUngrouped(); - //this._updateGraph(); - this.redraw(true); + + this.setRange(newStart, newEnd, false, true); + + this.startToFront = false; // revert to default + this.endToFront = true; // revert to default }; + /** - * update a group object with the group dataset entree - * - * @param group - * @param groupId - * @private + * 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 */ - 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.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(); - }; + Range.prototype.move = function(delta) { + // zoom start Date and end Date relative to the centerDate + var diff = (this.end - this.start); + + // apply new values + var newStart = this.start + diff * delta; + var newEnd = this.end + diff * delta; + + // TODO: reckon with min and max range + this.start = newStart; + this.end = newEnd; + }; /** - * this updates all groups, it is used when there is an update the the itemset. - * - * @private + * Move the range to a new center point + * @param {Number} moveTo New center point of the range */ - LineGraph.prototype._updateAllGroupData = function () { - if (this.itemsData != null) { - var groupsContent = {}; - var groupId; - for (groupId in this.groups) { - if (this.groups.hasOwnProperty(groupId)) { - groupsContent[groupId] = []; - } - } - for (var itemId in this.itemsData._data) { - if (this.itemsData._data.hasOwnProperty(itemId)) { - var item = this.itemsData._data[itemId]; - if (groupsContent[item.group] === undefined) { - throw new Error('Cannot find referenced group. Possible reason: items added before groups? Groups need to be added before items, as items refer to groups.') - } - item.x = util.convert(item.x,'Date'); - groupsContent[item.group].push(item); - } - } - for (groupId in this.groups) { - if (this.groups.hasOwnProperty(groupId)) { - this.groups[groupId].setItems(groupsContent[groupId]); - } - } - } + 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 = Range; + + +/***/ }, +/* 22 */ +/***/ function(module, exports, __webpack_require__) { + + var Hammer = __webpack_require__(19); /** - * 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 + * Fake a hammer.js gesture. Event can be a ScrollEvent or MouseMoveEvent + * @param {Element} element + * @param {Event} event */ - LineGraph.prototype._updateUngrouped = function() { - if (this.itemsData && this.itemsData != null) { - var ungroupedCounter = 0; - 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; - } - } - } + exports.fakeGesture = function(element, event) { + var eventType = null; - if (ungroupedCounter == 0) { - delete this.groups[UNGROUPED]; - this.legendLeft.removeGroup(UNGROUPED); - this.legendRight.removeGroup(UNGROUPED); - this.yAxisLeft.removeGroup(UNGROUPED); - this.yAxisRight.removeGroup(UNGROUPED); - } - else { - var group = {id: UNGROUPED, content: this.options.defaultGroup}; - this._updateGroup(group, UNGROUPED); - } + // 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; } - else { - delete this.groups[UNGROUPED]; - this.legendLeft.removeGroup(UNGROUPED); - this.legendRight.removeGroup(UNGROUPED); - this.yAxisLeft.removeGroup(UNGROUPED); - this.yAxisRight.removeGroup(UNGROUPED); + if (isNaN(gesture.center.pageY)) { + gesture.center.pageY = event.pageY; } - this.legendLeft.redraw(); - this.legendRight.redraw(); + return gesture; }; +/***/ }, +/* 23 */ +/***/ function(module, exports, __webpack_require__) { + /** - * Redraw the component, mandatory function + * 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 */ - LineGraph.prototype.redraw = function(forceGraphUpdate) { - var resized = false; + Component.prototype.redraw = function() { + // should be implemented by the component + return false; + }; - // calculate actual size and position - this.props.width = this.dom.frame.offsetWidth; - this.props.height = this.body.domProps.centerContainer.height; + /** + * Destroy the component. Cleanup DOM and event listeners + */ + Component.prototype.destroy = function() { + // should be implemented by the component + }; - // update the graph if there is no lastWidth or with, used for the initial draw - if (this.lastWidth === undefined && this.props.width) { - forceGraphUpdate = true; - } + /** + * 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); - // check if this component is resized - resized = this._isResized() || resized; + this.props._previousWidth = this.props.width; + this.props._previousHeight = this.props.height; - // 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.lastVisibleInterval = visibleInterval; + return resized; + }; + module.exports = Component; - // 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.props.width); - this.svg.style.left = util.option.asSize(-this.props.width); - // if the height of the graph is set as proportional, change the height of the svg - if ((this.options.height + '').indexOf("%") != -1 || this.updateSVGheightOnResize == true) { - this.updateSVGheight = true; - } - } +/***/ }, +/* 24 */ +/***/ function(module, exports, __webpack_require__) { - // update the height of the graph on each redraw of the graph. - if (this.updateSVGheight == true) { - if (this.options.graphHeight != this.body.domProps.centerContainer.height + 'px') { - this.options.graphHeight = this.body.domProps.centerContainer.height + 'px'; - this.svg.style.height = this.body.domProps.centerContainer.height + 'px'; - } - this.updateSVGheight = false; - } - else { - this.svg.style.height = ('' + this.options.graphHeight).replace('px','') + 'px'; - } + /** + * Created by Alex on 10/3/2014. + */ + var moment = __webpack_require__(2); - // zoomed is here to ensure that animations are shown correctly. - if (resized == true || zoomed == true || this.abortedGraphUpdate == true || forceGraphUpdate == true) { - resized = this._updateGraph() || resized; - } - else { - // move the whole svg while dragging - if (this.lastStart != 0) { - var offset = this.body.range.start - this.lastStart; - var range = this.body.range.end - this.body.range.start; - if (this.props.width != 0) { - var rangePerPixelInv = this.props.width/range; - var xOffset = offset * rangePerPixelInv; - this.svg.style.left = (-this.props.width - xOffset) + 'px'; + + /** + * used in Core to convert the options into a volatile variable + * + * @param Core + */ + exports.convertHiddenOptions = function(body, hiddenDates) { + body.hiddenDates = []; + if (hiddenDates) { + if (Array.isArray(hiddenDates) == true) { + for (var i = 0; i < hiddenDates.length; i++) { + if (hiddenDates[i].repeat === undefined) { + var dateItem = {}; + dateItem.start = moment(hiddenDates[i].start).toDate().valueOf(); + dateItem.end = moment(hiddenDates[i].end).toDate().valueOf(); + body.hiddenDates.push(dateItem); + } } + body.hiddenDates.sort(function (a, b) { + return a.start - b.start; + }); // sort by start time } } - - this.legendLeft.redraw(); - this.legendRight.redraw(); - return resized; }; /** - * Update and redraw the graph. - * + * create new entrees for the repeating hidden dates + * @param body + * @param hiddenDates */ - LineGraph.prototype._updateGraph = function () { - // reset the svg elements - DOMutil.prepareElements(this.svgElements); - if (this.props.width != 0 && this.itemsData != null) { - var group, i; - var preprocessedGroupData = {}; - var processedGroupData = {}; - var groupRanges = {}; - var changeCalled = false; + exports.updateHiddenDates = function (body, hiddenDates) { + if (hiddenDates && body.domProps.centerContainer.width !== undefined) { + exports.convertHiddenOptions(body, hiddenDates); - // getting group Ids - var groupIds = []; - for (var groupId in this.groups) { - if (this.groups.hasOwnProperty(groupId)) { - group = this.groups[groupId]; - if (group.visible == true && (this.options.groups.visibility[groupId] === undefined || this.options.groups.visibility[groupId] == true)) { - groupIds.push(groupId); - } - } - } - if (groupIds.length > 0) { - // this is the range of the SVG canvas - var minDate = this.body.util.toGlobalTime(-this.body.domProps.root.width); - var maxDate = this.body.util.toGlobalTime(2 * this.body.domProps.root.width); - var groupsData = {}; - // fill groups data, this only loads the data we require based on the timewindow - this._getRelevantData(groupIds, groupsData, minDate, maxDate); + var start = moment(body.range.start); + var end = moment(body.range.end); - // apply sampling, if disabled, it will pass through this function. - this._applySampling(groupIds, groupsData); - - // we transform the X coordinates to detect collisions - for (i = 0; i < groupIds.length; i++) { - preprocessedGroupData[groupIds[i]] = this._convertXcoordinates(groupsData[groupIds[i]]); - } + var totalRange = (body.range.end - body.range.start); + var pixelTime = totalRange / body.domProps.centerContainer.width; - // now all needed data has been collected we start the processing. - this._getYRanges(groupIds, preprocessedGroupData, groupRanges); + for (var i = 0; i < hiddenDates.length; i++) { + if (hiddenDates[i].repeat !== undefined) { + var startDate = moment(hiddenDates[i].start); + var endDate = moment(hiddenDates[i].end); - // 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); - var MAX_CYCLES = 5; - if (changeCalled == true && this.COUNTER < MAX_CYCLES) { - DOMutil.cleanupElements(this.svgElements); - this.abortedGraphUpdate = true; - this.COUNTER++; - this.body.emitter.emit('change'); - return true; - } - else { - if (this.COUNTER > MAX_CYCLES) { - console.log("WARNING: there may be an infinite loop in the _updateGraph emitter cycle.") + if (startDate._d == "Invalid Date") { + throw new Error("Supplied start date is not valid: " + hiddenDates[i].start); } - this.COUNTER = 0; - this.abortedGraphUpdate = false; - - // 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[groupIds[i]] = this._convertYcoordinates(groupsData[groupIds[i]], group); + if (endDate._d == "Invalid Date") { + throw new Error("Supplied end date is not valid: " + hiddenDates[i].end); } - // draw the groups - for (i = 0; i < groupIds.length; i++) { - group = this.groups[groupIds[i]]; - if (group.options.style != 'bar') { // bar needs to be drawn enmasse - group.draw(processedGroupData[groupIds[i]], group, this.framework); - } - } - BarGraphFunctions.draw(groupIds, processedGroupData, this.framework); - } - } - } + var duration = endDate - startDate; + if (duration >= 4 * pixelTime) { - // cleanup unused svg elements - DOMutil.cleanupElements(this.svgElements); - return false; - }; + var offset = 0; + var runUntil = end.clone(); + switch (hiddenDates[i].repeat) { + case "daily": // case of time + if (startDate.day() != endDate.day()) { + offset = 1; + } + startDate.dayOfYear(start.dayOfYear()); + startDate.year(start.year()); + startDate.subtract(7,'days'); + endDate.dayOfYear(start.dayOfYear()); + endDate.year(start.year()); + endDate.subtract(7 - offset,'days'); - /** - * 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. - * - * @param {array} groupIds - * @param {object} groupsData - * @param {date} minDate - * @param {date} maxDate - * @private - */ - LineGraph.prototype._getRelevantData = function (groupIds, groupsData, minDate, maxDate) { - var group, i, j, item; - if (groupIds.length > 0) { - for (i = 0; i < groupIds.length; i++) { - group = this.groups[groupIds[i]]; - groupsData[groupIds[i]] = []; - var dataContainer = groupsData[groupIds[i]]; - // optimization for sorted data - if (group.options.sort == true) { - var guess = Math.max(0, util.binarySearchValue(group.itemsData, minDate, 'x', 'before')); - for (j = guess; j < group.itemsData.length; j++) { - item = group.itemsData[j]; - if (item !== undefined) { - if (item.x > maxDate) { - dataContainer.push(item); + runUntil.add(1, 'weeks'); break; - } - else { - dataContainer.push(item); - } - } - } - } - else { - for (j = 0; j < group.itemsData.length; j++) { - item = group.itemsData[j]; - if (item !== undefined) { - if (item.x > minDate && item.x < maxDate) { - dataContainer.push(item); - } - } - } - } - } - } - }; + case "weekly": + var dayOffset = endDate.diff(startDate,'days') + var day = startDate.day(); + // set the start date to the range.start + startDate.date(start.date()); + startDate.month(start.month()); + startDate.year(start.year()); + endDate = startDate.clone(); - /** - * - * @param groupIds - * @param groupsData - * @private - */ - LineGraph.prototype._applySampling = function (groupIds, groupsData) { - var group; - if (groupIds.length > 0) { - for (var i = 0; i < groupIds.length; i++) { - group = this.groups[groupIds[i]]; - if (group.options.sampling == true) { - var dataContainer = groupsData[groupIds[i]]; - if (dataContainer.length > 0) { - var increment = 1; - var amountOfPoints = dataContainer.length; + // force + startDate.day(day); + endDate.day(day); + endDate.add(dayOffset,'days'); - // 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. - var xDistance = this.body.util.toGlobalScreen(dataContainer[dataContainer.length - 1].x) - this.body.util.toGlobalScreen(dataContainer[0].x); - var pointsPerPixel = amountOfPoints / xDistance; - increment = Math.min(Math.ceil(0.2 * amountOfPoints), Math.max(1, Math.round(pointsPerPixel))); + startDate.subtract(1,'weeks'); + endDate.subtract(1,'weeks'); - var sampledData = []; - for (var j = 0; j < amountOfPoints; j += increment) { - sampledData.push(dataContainer[j]); + runUntil.add(1, 'weeks'); + break + case "monthly": + if (startDate.month() != endDate.month()) { + offset = 1; + } + startDate.month(start.month()); + startDate.year(start.year()); + startDate.subtract(1,'months'); + + endDate.month(start.month()); + endDate.year(start.year()); + endDate.subtract(1,'months'); + endDate.add(offset,'months'); + + runUntil.add(1, 'months'); + break; + case "yearly": + if (startDate.year() != endDate.year()) { + offset = 1; + } + startDate.year(start.year()); + startDate.subtract(1,'years'); + endDate.year(start.year()); + endDate.subtract(1,'years'); + endDate.add(offset,'years'); + runUntil.add(1, 'years'); + break; + default: + console.log("Wrong repeat format, allowed are: daily, weekly, monthly, yearly. Given:", hiddenDates[i].repeat); + return; } - groupsData[groupIds[i]] = sampledData; + while (startDate < runUntil) { + body.hiddenDates.push({start: startDate.valueOf(), end: endDate.valueOf()}); + switch (hiddenDates[i].repeat) { + case "daily": + startDate.add(1, 'days'); + endDate.add(1, 'days'); + break; + case "weekly": + startDate.add(1, 'weeks'); + endDate.add(1, 'weeks'); + break + case "monthly": + startDate.add(1, 'months'); + endDate.add(1, 'months'); + break; + case "yearly": + startDate.add(1, 'y'); + endDate.add(1, 'y'); + break; + default: + console.log("Wrong repeat format, allowed are: daily, weekly, monthly, yearly. Given:", hiddenDates[i].repeat); + return; + } + } + body.hiddenDates.push({start: startDate.valueOf(), end: endDate.valueOf()}); } } } + // remove duplicates, merge where possible + exports.removeDuplicates(body); + // ensure the new positions are not on hidden dates + var startHidden = exports.isHidden(body.range.start, body.hiddenDates); + var endHidden = exports.isHidden(body.range.end,body.hiddenDates); + var rangeStart = body.range.start; + var rangeEnd = body.range.end; + if (startHidden.hidden == true) {rangeStart = body.range.startToFront == true ? startHidden.startDate - 1 : startHidden.endDate + 1;} + if (endHidden.hidden == true) {rangeEnd = body.range.endToFront == true ? endHidden.startDate - 1 : endHidden.endDate + 1;} + if (startHidden.hidden == true || endHidden.hidden == true) { + body.range._applyRange(rangeStart, rangeEnd); + } } - }; + + } /** - * - * - * @param {array} groupIds - * @param {object} groupsData - * @param {object} groupRanges | this is being filled here - * @private + * remove duplicates from the hidden dates list. Duplicates are evil. They mess everything up. + * Scales with N^2 + * @param body */ - LineGraph.prototype._getYRanges = function (groupIds, groupsData, groupRanges) { - var groupData, group, i; - var barCombinedDataLeft = []; - var barCombinedDataRight = []; - var options; - if (groupIds.length > 0) { - for (i = 0; i < groupIds.length; i++) { - groupData = groupsData[groupIds[i]]; - options = this.groups[groupIds[i]].options; - if (groupData.length > 0) { - group = this.groups[groupIds[i]]; - // if bar graphs are stacked, their range need to be handled differently and accumulated over all groups. - if (options.barChart.handleOverlap == 'stack' && options.style == 'bar') { - if (options.yAxisOrientation == 'left') {barCombinedDataLeft = barCombinedDataLeft.concat(group.getYRange(groupData)) ;} - else {barCombinedDataRight = barCombinedDataRight.concat(group.getYRange(groupData));} + exports.removeDuplicates = function(body) { + var hiddenDates = body.hiddenDates; + var safeDates = []; + for (var i = 0; i < hiddenDates.length; i++) { + for (var j = 0; j < hiddenDates.length; j++) { + if (i != j && hiddenDates[j].remove != true && hiddenDates[i].remove != true) { + // j inside i + if (hiddenDates[j].start >= hiddenDates[i].start && hiddenDates[j].end <= hiddenDates[i].end) { + hiddenDates[j].remove = true; } - else { - groupRanges[groupIds[i]] = group.getYRange(groupData,groupIds[i]); + // j start inside i + else if (hiddenDates[j].start >= hiddenDates[i].start && hiddenDates[j].start <= hiddenDates[i].end) { + hiddenDates[i].end = hiddenDates[j].end; + hiddenDates[j].remove = true; + } + // j end inside i + else if (hiddenDates[j].end >= hiddenDates[i].start && hiddenDates[j].end <= hiddenDates[i].end) { + hiddenDates[i].start = hiddenDates[j].start; + hiddenDates[j].remove = true; } } } + } - // if bar graphs are stacked, their range need to be handled differently and accumulated over all groups. - BarGraphFunctions.getStackedBarYRange(barCombinedDataLeft , groupRanges, groupIds, '__barchartLeft' , 'left' ); - BarGraphFunctions.getStackedBarYRange(barCombinedDataRight, groupRanges, groupIds, '__barchartRight', 'right'); + for (var i = 0; i < hiddenDates.length; i++) { + if (hiddenDates[i].remove !== true) { + safeDates.push(hiddenDates[i]); + } } - }; + body.hiddenDates = safeDates; + body.hiddenDates.sort(function (a, b) { + return a.start - b.start; + }); // sort by start time + } + + exports.printDates = function(dates) { + for (var i =0; i < dates.length; i++) { + console.log(i, new Date(dates[i].start),new Date(dates[i].end), dates[i].start, dates[i].end, dates[i].remove); + } + } /** - * this sets the Y ranges for the Y axis. It also determines which of the axis should be shown or hidden. - * @param {Array} groupIds - * @param {Object} groupRanges - * @private + * Used in TimeStep to avoid the hidden times. + * @param timeStep + * @param previousTime */ - LineGraph.prototype._updateYAxis = function (groupIds, groupRanges) { - var resized = false; - var yAxisLeftUsed = false; - var yAxisRightUsed = false; - var minLeft = 1e9, minRight = 1e9, maxLeft = -1e9, maxRight = -1e9, minVal, maxVal; - // if groups are present - if (groupIds.length > 0) { - // this is here to make sure that if there are no items in the axis but there are groups, that there is no infinite draw/redraw loop. - for (var i = 0; i < groupIds.length; i++) { - var group = this.groups[groupIds[i]]; - if (group && group.options.yAxisOrientation != 'right') { - yAxisLeftUsed = true; - minLeft = 0; - maxLeft = 0; - } - else if (group && group.options.yAxisOrientation) { - yAxisRightUsed = true; - minRight = 0; - maxRight = 0; - } + exports.stepOverHiddenDates = function(timeStep, previousTime) { + var stepInHidden = false; + var currentValue = timeStep.current.valueOf(); + for (var i = 0; i < timeStep.hiddenDates.length; i++) { + var startDate = timeStep.hiddenDates[i].start; + var endDate = timeStep.hiddenDates[i].end; + if (currentValue >= startDate && currentValue < endDate) { + stepInHidden = true; + break; } + } - // if there are items: - for (var i = 0; i < groupIds.length; i++) { - if (groupRanges.hasOwnProperty(groupIds[i])) { - if (groupRanges[groupIds[i]].ignore !== true) { - minVal = groupRanges[groupIds[i]].min; - maxVal = groupRanges[groupIds[i]].max; - - if (groupRanges[groupIds[i]].yAxisOrientation != 'right') { - 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 (stepInHidden == true && currentValue < timeStep._end.valueOf() && currentValue != previousTime) { + var prevValue = moment(previousTime); + var newValue = moment(endDate); + //check if the next step should be major + if (prevValue.year() != newValue.year()) {timeStep.switchedYear = true;} + else if (prevValue.month() != newValue.month()) {timeStep.switchedMonth = true;} + else if (prevValue.dayOfYear() != newValue.dayOfYear()) {timeStep.switchedDay = true;} - if (yAxisLeftUsed == true) { - this.yAxisLeft.setRange(minLeft, maxLeft); - } - if (yAxisRightUsed == true) { - this.yAxisRight.setRange(minRight, maxRight); - } + timeStep.current = newValue.toDate(); } - resized = this._toggleAxisVisiblity(yAxisLeftUsed , this.yAxisLeft) || resized; - resized = this._toggleAxisVisiblity(yAxisRightUsed, this.yAxisRight) || resized; + }; - if (yAxisRightUsed == true && yAxisLeftUsed == true) { - this.yAxisLeft.drawIcons = true; - this.yAxisRight.drawIcons = true; - } - else { - this.yAxisLeft.drawIcons = false; - this.yAxisRight.drawIcons = false; - } - this.yAxisRight.master = !yAxisLeftUsed; - if (this.yAxisRight.master == false) { - if (yAxisRightUsed == true) {this.yAxisLeft.lineOffset = this.yAxisRight.width;} - else {this.yAxisLeft.lineOffset = 0;} - resized = this.yAxisLeft.redraw() || resized; - this.yAxisRight.stepPixelsForced = this.yAxisLeft.stepPixels; - this.yAxisRight.zeroCrossing = this.yAxisLeft.zeroCrossing; - resized = this.yAxisRight.redraw() || resized; + ///** + // * Used in TimeStep to avoid the hidden times. + // * @param timeStep + // * @param previousTime + // */ + //exports.checkFirstStep = function(timeStep) { + // var stepInHidden = false; + // var currentValue = timeStep.current.valueOf(); + // for (var i = 0; i < timeStep.hiddenDates.length; i++) { + // var startDate = timeStep.hiddenDates[i].start; + // var endDate = timeStep.hiddenDates[i].end; + // if (currentValue >= startDate && currentValue < endDate) { + // stepInHidden = true; + // break; + // } + // } + // + // if (stepInHidden == true && currentValue <= timeStep._end.valueOf()) { + // var newValue = moment(endDate); + // timeStep.current = newValue.toDate(); + // } + //}; + + /** + * replaces the Core toScreen methods + * @param Core + * @param time + * @param width + * @returns {number} + */ + exports.toScreen = function(Core, time, width) { + if (Core.body.hiddenDates.length == 0) { + var conversion = Core.range.conversion(width); + return (time.valueOf() - conversion.offset) * conversion.scale; } else { - resized = this.yAxisRight.redraw() || resized; - } + var hidden = exports.isHidden(time, Core.body.hiddenDates) + if (hidden.hidden == true) { + time = hidden.startDate; + } - // clean the accumulated lists - if (groupIds.indexOf('__barchartLeft') != -1) { - groupIds.splice(groupIds.indexOf('__barchartLeft'),1); - } - if (groupIds.indexOf('__barchartRight') != -1) { - groupIds.splice(groupIds.indexOf('__barchartRight'),1); - } + var duration = exports.getHiddenDurationBetween(Core.body.hiddenDates, Core.range.start, Core.range.end); + time = exports.correctTimeForHidden(Core.body.hiddenDates, Core.range, time); - return resized; + var conversion = Core.range.conversion(width, duration); + return (time.valueOf() - conversion.offset) * conversion.scale; + } }; /** - * 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 + * Replaces the core toTime methods + * @param body + * @param range + * @param x + * @param width + * @returns {Date} */ - LineGraph.prototype._toggleAxisVisiblity = function (axisUsed, axis) { - var changed = false; - if (axisUsed == false) { - if (axis.dom.frame.parentNode && axis.hidden == false) { - axis.hide() - changed = true; - } + exports.toTime = function(Core, x, width) { + if (Core.body.hiddenDates.length == 0) { + var conversion = Core.range.conversion(width); + return new Date(x / conversion.scale + conversion.offset); } else { - if (!axis.dom.frame.parentNode && axis.hidden == true) { - axis.show(); - changed = true; - } + var hiddenDuration = exports.getHiddenDurationBetween(Core.body.hiddenDates, Core.range.start, Core.range.end); + var totalDuration = Core.range.end - Core.range.start - hiddenDuration; + var partialDuration = totalDuration * x / width; + var accumulatedHiddenDuration = exports.getAccumulatedHiddenDuration(Core.body.hiddenDates, Core.range, partialDuration); + + var newTime = new Date(accumulatedHiddenDuration + partialDuration + Core.range.start); + return newTime; } - return changed; }; /** - * 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. + * Support function * - * @param datapoints - * @returns {Array} - * @private + * @param hiddenDates + * @param range + * @returns {number} */ - LineGraph.prototype._convertXcoordinates = function (datapoints) { - var extractedData = []; - var xValue, yValue; - var toScreen = this.body.util.toScreen; - - for (var i = 0; i < datapoints.length; i++) { - xValue = toScreen(datapoints[i].x) + this.props.width; - yValue = datapoints[i].y; - extractedData.push({x: xValue, y: yValue}); + exports.getHiddenDurationBetween = function(hiddenDates, start, end) { + var duration = 0; + for (var i = 0; i < hiddenDates.length; i++) { + var startDate = hiddenDates[i].start; + var endDate = hiddenDates[i].end; + // if time after the cutout, and the + if (startDate >= start && endDate < end) { + duration += endDate - startDate; + } } - - return extractedData; + return duration; }; /** - * 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 - * @param group - * @returns {Array} - * @private - */ - LineGraph.prototype._convertYcoordinates = function (datapoints, group) { - var extractedData = []; - var xValue, yValue; - var toScreen = this.body.util.toScreen; - var axis = this.yAxisLeft; - var svgHeight = Number(this.svg.style.height.replace('px','')); - if (group.options.yAxisOrientation == 'right') { - axis = this.yAxisRight; - } + * Support function + * @param hiddenDates + * @param range + * @param time + * @returns {{duration: number, time: *, offset: number}} + */ + exports.correctTimeForHidden = function(hiddenDates, range, time) { + time = moment(time).toDate().valueOf(); + time -= exports.getHiddenDurationBefore(hiddenDates,range,time); + return time; + }; - for (var i = 0; i < datapoints.length; i++) { - var labelValue; - //if (datapoints[i].label) { - // labelValue = datapoints[i].label; - //} - //else { - // labelValue = null; - //} - labelValue = datapoints[i].label ? datapoints[i].label : null; - xValue = toScreen(datapoints[i].x) + this.props.width; - yValue = Math.round(axis.convertValue(datapoints[i].y)); - extractedData.push({x: xValue, y: yValue, label:labelValue}); + exports.getHiddenDurationBefore = function(hiddenDates, range, time) { + var timeOffset = 0; + time = moment(time).toDate().valueOf(); + + for (var i = 0; i < hiddenDates.length; i++) { + var startDate = hiddenDates[i].start; + var endDate = hiddenDates[i].end; + // if time after the cutout, and the + if (startDate >= range.start && endDate < range.end) { + if (time >= endDate) { + timeOffset += (endDate - startDate); + } + } } + return timeOffset; + } - group.setZeroPosition(Math.min(svgHeight, axis.convertValue(0))); + /** + * sum the duration from start to finish, including the hidden duration, + * until the required amount has been reached, return the accumulated hidden duration + * @param hiddenDates + * @param range + * @param time + * @returns {{duration: number, time: *, offset: number}} + */ + exports.getAccumulatedHiddenDuration = function(hiddenDates, range, requiredDuration) { + var hiddenDuration = 0; + var duration = 0; + var previousPoint = range.start; + //exports.printDates(hiddenDates) + for (var i = 0; i < hiddenDates.length; i++) { + var startDate = hiddenDates[i].start; + var endDate = hiddenDates[i].end; + // if time after the cutout, and the + if (startDate >= range.start && endDate < range.end) { + duration += startDate - previousPoint; + previousPoint = endDate; + if (duration >= requiredDuration) { + break; + } + else { + hiddenDuration += endDate - startDate; + } + } + } - return extractedData; + return hiddenDuration; }; - module.exports = LineGraph; + /** + * used to step over to either side of a hidden block. Correction is disabled on tablets, might be set to true + * @param hiddenDates + * @param time + * @param direction + * @param correctionEnabled + * @returns {*} + */ + exports.snapAwayFromHidden = function(hiddenDates, time, direction, correctionEnabled) { + var isHidden = exports.isHidden(time, hiddenDates); + if (isHidden.hidden == true) { + if (direction < 0) { + if (correctionEnabled == true) { + return isHidden.startDate - (isHidden.endDate - time) - 1; + } + else { + return isHidden.startDate - 1; + } + } + else { + if (correctionEnabled == true) { + return isHidden.endDate + (time - isHidden.startDate) + 1; + } + else { + return isHidden.endDate + 1; + } + } + } + else { + return time; + } + + } + + + /** + * Check if a time is hidden + * + * @param time + * @param hiddenDates + * @returns {{hidden: boolean, startDate: Window.start, endDate: *}} + */ + exports.isHidden = function(time, hiddenDates) { + for (var i = 0; i < hiddenDates.length; i++) { + var startDate = hiddenDates[i].start; + var endDate = hiddenDates[i].end; + + if (time >= startDate && time < endDate) { // if the start is entering a hidden zone + return {hidden: true, startDate: startDate, endDate: endDate}; + break; + } + } + return {hidden: false, startDate: startDate, endDate: endDate}; + } /***/ }, -/* 30 */ +/* 25 */ /***/ function(module, exports, __webpack_require__) { + var Emitter = __webpack_require__(11); + var Hammer = __webpack_require__(19); var util = __webpack_require__(1); - var Component = __webpack_require__(20); - var TimeStep = __webpack_require__(19); - var DateUtil = __webpack_require__(15); - var moment = __webpack_require__(44); + var DataSet = __webpack_require__(7); + var DataView = __webpack_require__(9); + var Range = __webpack_require__(21); + var ItemSet = __webpack_require__(26); + var Activator = __webpack_require__(36); + var DateUtil = __webpack_require__(24); /** - * 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 + * 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 TimeAxis (body, options) { - this.dom = { - foreground: null, - lines: [], - majorTexts: [], - minorTexts: [], - redundant: { - lines: [], - majorTexts: [], - minorTexts: [] + function Core () {} + + // turn Core into an event emitter + Emitter(Core.prototype); + + /** + * Create the main DOM for the Core: a root panel containing left, right, + * top, bottom, content, and background panel. + * @param {Element} container The container element where the Core will + * be attached. + * @private + */ + Core.prototype._create = function (container) { + this.dom = {}; + + this.dom.root = document.createElement('div'); + this.dom.background = document.createElement('div'); + this.dom.backgroundVertical = document.createElement('div'); + this.dom.backgroundHorizontal = document.createElement('div'); + this.dom.centerContainer = document.createElement('div'); + this.dom.leftContainer = document.createElement('div'); + this.dom.rightContainer = document.createElement('div'); + this.dom.center = document.createElement('div'); + this.dom.left = document.createElement('div'); + this.dom.right = document.createElement('div'); + this.dom.top = document.createElement('div'); + this.dom.bottom = document.createElement('div'); + this.dom.shadowTop = document.createElement('div'); + this.dom.shadowBottom = document.createElement('div'); + this.dom.shadowTopLeft = document.createElement('div'); + this.dom.shadowBottomLeft = document.createElement('div'); + this.dom.shadowTopRight = document.createElement('div'); + this.dom.shadowBottomRight = document.createElement('div'); + + this.dom.root.className = 'vis timeline root'; + 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('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)); + + var me = this; + this.on('change', function (properties) { + if (properties && properties.queue == true) { + // redraw once on next tick + if (!me._redrawTimer) { + me._redrawTimer = setTimeout(function () { + me._redrawTimer = null; + me._redraw(); + }, 0) + } } - }; - this.props = { - range: { - start: 0, - end: 0, - minimumStep: 0 - }, - lineTop: 0 - }; + else { + // redraw immediately + me._redraw(); + } + }); - this.defaultOptions = { - orientation: 'bottom', // supported: 'top', 'bottom' - // TODO: implement timeaxis orientations 'left' and 'right' - showMinorLabels: true, - showMajorLabels: true, - format: null, - timeAxis: null - }; - this.options = util.extend({}, this.defaultOptions); + // create event listeners for all interesting events, these events will be + // emitted via emitter + this.hammer = Hammer(this.dom.root, { + preventDefault: true + }); + this.listeners = {}; - this.body = body; + 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)); + if (me.isActive()) { + me.emit.apply(me, args); + } + }; + me.hammer.on(event, listener); + me.listeners[event] = listener; + }); - // create the HTML DOM - this._create(); + // 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 - this.setOptions(options); - } + this.redrawCount = 0; - TimeAxis.prototype = new Component(); + // attach the root panel to the provided container + if (!container) throw new Error('No container provided'); + container.appendChild(this.dom.root); + }; /** - * Set options for the TimeAxis. - * Parameters will be merged in current options. - * @param {Object} options Available options: - * {string} [orientation] - * {boolean} [showMinorLabels] - * {boolean} [showMajorLabels] + * 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 */ - TimeAxis.prototype.setOptions = function(options) { + Core.prototype.setOptions = function (options) { if (options) { - // copy all options that we know - util.selectiveExtend([ - 'orientation', - 'showMinorLabels', - 'showMajorLabels', - 'hiddenDates', - 'format', - 'timeAxis' - ], this.options, options); + // copy the known options + var fields = ['width', 'height', 'minHeight', 'maxHeight', 'autoResize', 'start', 'end', 'orientation', 'clickToUse', 'dataAttributes', 'hiddenDates']; + util.selectiveExtend(fields, this.options, options); - // apply locale to moment.js - // TODO: not so nice, this is applied globally to moment.js - if ('locale' in options) { - if (typeof moment.locale === 'function') { - // moment.js 2.8.1+ - moment.locale(options.locale); + if ('hiddenDates' in this.options) { + DateUtil.convertHiddenOptions(this.body, this.options.hiddenDates); + } + + if ('clickToUse' in options) { + if (options.clickToUse) { + if (!this.activator) { + this.activator = new Activator(this.dom.root); + } } else { - moment.lang(options.locale); + if (this.activator) { + this.activator.destroy(); + delete this.activator; + } } } + + // enable/disable autoResize + this._initAutoResize(); } - }; - /** - * Create the HTML DOM for the TimeAxis - */ - TimeAxis.prototype._create = function() { - this.dom.foreground = document.createElement('div'); - this.dom.background = document.createElement('div'); + // propagate options to all components + this.components.forEach(function (component) { + component.setOptions(options); + }); - this.dom.foreground.className = 'timeaxis foreground'; - this.dom.background.className = 'timeaxis background'; + // 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.'); + } + + // redraw everything + this._redraw(); }; /** - * Destroy the TimeAxis + * Returns true when the Timeline is active. + * @returns {boolean} */ - TimeAxis.prototype.destroy = function() { - // remove from DOM - if (this.dom.foreground.parentNode) { - this.dom.foreground.parentNode.removeChild(this.dom.foreground); - } - if (this.dom.background.parentNode) { - this.dom.background.parentNode.removeChild(this.dom.background); - } - - this.body = null; + Core.prototype.isActive = function () { + return !this.activator || this.activator.active; }; /** - * Repaint the component - * @return {boolean} Returns true if the component is resized + * Destroy the Core, clean up all DOM elements and event listeners. */ - TimeAxis.prototype.redraw = function () { - var options = this.options; - var props = this.props; - var foreground = this.dom.foreground; - var background = this.dom.background; + Core.prototype.destroy = function () { + // unbind datasets + this.clear(); - // 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); + // remove all event listeners + this.off(); - // calculate character width and height - this._calculateCharSize(); + // stop checking for changed size + this._stopAutoResize(); - // 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; + // remove from DOM + if (this.dom.root.parentNode) { + this.dom.root.parentNode.removeChild(this.dom.root); + } + this.dom = null; - // 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; + // remove Activator + if (this.activator) { + this.activator.destroy(); + delete this.activator; + } - 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 + // cleanup hammer touch events + for (var event in this.listeners) { + if (this.listeners.hasOwnProperty(event)) { + delete this.listeners[event]; + } + } + this.listeners = null; + this.hammer = null; - // 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); + // give all components the opportunity to cleanup + this.components.forEach(function (component) { + component.destroy(); + }); - foreground.style.height = this.props.height + 'px'; + this.body = null; + }; - this._repaintLabels(); - // put DOM online again (at the same place) - if (foregroundNextSibling) { - parent.insertBefore(foreground, foregroundNextSibling); - } - else { - parent.appendChild(foreground) - } - if (backgroundNextSibling) { - this.body.dom.backgroundVertical.insertBefore(background, backgroundNextSibling); - } - else { - this.body.dom.backgroundVertical.appendChild(background) + /** + * Set a custom time bar + * @param {Date} time + */ + Core.prototype.setCustomTime = function (time) { + if (!this.customTime) { + throw new Error('Cannot get custom time: Custom time bar is not enabled'); } - return this._isResized() || parentChanged; + this.customTime.setCustomTime(time); }; /** - * Repaint major and minor text labels and vertical grid lines - * @private + * Retrieve the current custom time. + * @return {Date} customTime */ - 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'); - var end = util.convert(this.body.range.end, 'Number'); - var timeLabelsize = this.body.util.toTime((this.props.minorCharWidth || 10) * 7).valueOf(); - var minimumStep = timeLabelsize - DateUtil.getHiddenDurationBefore(this.body.hiddenDates, this.body.range, timeLabelsize); - minimumStep -= this.body.util.toTime(0).valueOf(); - - var step = new TimeStep(new Date(start), new Date(end), minimumStep, this.body.hiddenDates); - if (this.options.format) { - step.setFormat(this.options.format); - } - if (this.options.timeAxis) { - step.setScale(this.options.timeAxis); - } - 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.lines = dom.lines; - dom.redundant.majorTexts = dom.majorTexts; - dom.redundant.minorTexts = dom.minorTexts; - dom.lines = []; - dom.majorTexts = []; - dom.minorTexts = []; - - var cur; - var x = 0; - var isMajor; - var xPrev = 0; - var width = 0; - var prevLine; - var xFirstMajorLabel = undefined; - var max = 0; - var className; - - step.first(); - while (step.hasNext() && max < 1000) { - max++; - - cur = step.getCurrent(); - isMajor = step.isMajor(); - className = step.getClassName(); - - xPrev = x; - x = this.body.util.toScreen(cur); - width = x - xPrev; - if (prevLine) { - prevLine.style.width = width + 'px'; - } - - if (this.options.showMinorLabels) { - this._repaintMinorText(x, step.getLabelMinor(), orientation, className); - } - - if (isMajor && this.options.showMajorLabels) { - if (x > 0) { - if (xFirstMajorLabel == undefined) { - xFirstMajorLabel = x; - } - this._repaintMajorText(x, step.getLabelMajor(), orientation, className); - } - prevLine = this._repaintMajorLine(x, orientation, className); - } - else { - prevLine = this._repaintMinorLine(x, orientation, className); - } - - 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, className); - } + Core.prototype.getCustomTime = function() { + if (!this.customTime) { + throw new Error('Cannot get custom time: Custom time bar is not enabled'); } - // 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); - } - } - }); + return this.customTime.getCustomTime(); }; - /** - * Create a minor label for the axis at position x - * @param {Number} x - * @param {String} text - * @param {String} orientation "top" or "bottom" (default) - * @param {String} className - * @private - */ - TimeAxis.prototype._repaintMinorText = function (x, text, orientation, className) { - // 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); - 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.className = 'text minor ' + className; - //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) - * @param {String} className - * @private + * Get the id's of the currently visible items. + * @returns {Array} The ids of the visible items */ - TimeAxis.prototype._repaintMajorText = function (x, text, orientation, className) { - // reuse redundant label - var label = this.dom.redundant.majorTexts.shift(); - - if (!label) { - // create label - var content = document.createTextNode(text); - label = document.createElement('div'); - label.appendChild(content); - this.dom.foreground.appendChild(label); - } - this.dom.majorTexts.push(label); + Core.prototype.getVisibleItems = function() { + return this.itemSet && this.itemSet.getVisibleItems() || []; + }; - label.childNodes[0].nodeValue = text; - label.className = 'text major ' + className; - //label.title = title; // TODO: this is a heavy operation - label.style.top = (orientation == 'top') ? '0' : (this.props.minorLabelHeight + 'px'); - label.style.left = x + 'px'; - }; /** - * Create a minor line for the axis at position x - * @param {Number} x - * @param {String} orientation "top" or "bottom" (default) - * @param {String} className - * @return {Element} Returns the created line - * @private + * 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} */ - TimeAxis.prototype._repaintMinorLine = function (x, orientation, className) { - // reuse redundant line - var line = this.dom.redundant.lines.shift(); - if (!line) { - // create vertical line - line = document.createElement('div'); - this.dom.background.appendChild(line); + Core.prototype.clear = function(what) { + // clear items + if (!what || what.items) { + this.setItems(null); } - this.dom.lines.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'; + // clear groups + if (!what || what.groups) { + this.setGroups(null); } - line.style.height = props.minorLineHeight + 'px'; - line.style.left = (x - props.minorLineWidth / 2) + 'px'; - line.className = 'grid vertical minor ' + className; + // clear options of timeline and of each of the components + if (!what || what.options) { + this.components.forEach(function (component) { + component.setOptions(component.defaultOptions); + }); - return line; + this.setOptions(this.defaultOptions); // this will also do a redraw + } }; /** - * Create a Major line for the axis at position x - * @param {Number} x - * @param {String} orientation "top" or "bottom" (default) - * @param {String} className - * @return {Element} Returns the created line - * @private + * Set Core window such that it fits all items + * @param {Object} [options] Available options: + * `animate: boolean | number` + * If true (default), the range is animated + * smoothly to the new window. + * If a number, the number is taken as duration + * for the animation. Default duration is 500 ms. */ - TimeAxis.prototype._repaintMajorLine = function (x, orientation, className) { - // reuse redundant line - var line = this.dom.redundant.lines.shift(); - if (!line) { - // create vertical line - line = document.createElement('div'); - this.dom.background.appendChild(line); - } - this.dom.lines.push(line); + Core.prototype.fit = function(options) { + var range = this._getDataRange(); - var props = this.props; - if (orientation == 'top') { - line.style.top = '0'; - } - else { - line.style.top = this.body.domProps.top.height + 'px'; + // skip range set if there is no start and end date + if (range.start === null && range.end === null) { + return; } - line.style.left = (x - props.majorLineWidth / 2) + 'px'; - line.style.height = props.majorLineHeight + 'px'; - - line.className = 'grid vertical major ' + className; - return line; + var animate = (options && options.animate !== undefined) ? options.animate : true; + this.range.setRange(range.start, range.end, animate); }; /** - * 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 + * Calculate the data range of the items and applies a 5% window around it. + * @returns {{start: Date | null, end: Date | null}} + * @protected */ - 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'; + Core.prototype._getDataRange = function() { + // apply the data range as range + var dataRange = this.getItemRange(); - this.dom.measureCharMinor.appendChild(document.createTextNode('0')); - this.dom.foreground.appendChild(this.dom.measureCharMinor); + // 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); } - this.props.minorCharHeight = this.dom.measureCharMinor.clientHeight; - this.props.minorCharWidth = this.dom.measureCharMinor.clientWidth; - - // 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 major measure'; - this.dom.measureCharMajor.style.position = 'absolute'; - this.dom.measureCharMajor.appendChild(document.createTextNode('0')); - this.dom.foreground.appendChild(this.dom.measureCharMajor); + return { + start: start, + end: end } - this.props.majorCharHeight = this.dom.measureCharMajor.clientHeight; - this.props.majorCharWidth = this.dom.measureCharMajor.clientWidth; - }; - - module.exports = TimeAxis; - - -/***/ }, -/* 31 */ -/***/ function(module, exports, __webpack_require__) { - - var Hammer = __webpack_require__(45); - var util = __webpack_require__(1); - - /** - * @constructor Item - * @param {Object} data Object containing (optional) parameters type, - * start, end, content, group, className. - * @param {{toScreen: function, toTime: function}} conversion - * Conversion functions from time to screen and vice versa - * @param {Object} options Configuration options - * // TODO: describe available options - */ - function Item (data, conversion, options) { - this.id = null; - this.parent = null; - this.data = data; - this.dom = null; - this.conversion = conversion || {}; - this.options = options || {}; - - this.selected = false; - this.displayed = false; - this.dirty = true; - - this.top = null; - this.left = null; - this.width = null; - this.height = null; - } - - Item.prototype.stack = true; - - /** - * Select current item - */ - Item.prototype.select = function() { - this.selected = true; - this.dirty = true; - if (this.displayed) this.redraw(); - }; - - /** - * Unselect current item - */ - Item.prototype.unselect = function() { - this.selected = false; - this.dirty = true; - if (this.displayed) this.redraw(); - }; - - /** - * Set data for the item. Existing data will be updated. The id should not - * be changed. When the item is displayed, it will be redrawn immediately. - * @param {Object} data - */ - Item.prototype.setData = function(data) { - this.data = data; - this.dirty = true; - if (this.displayed) this.redraw(); }; /** - * Set a parent for the item - * @param {ItemSet | Group} parent + * Set the visible window. Both parameters are optional, you can change only + * start or only end. Syntax: + * + * TimeLine.setWindow(start, end) + * TimeLine.setWindow(start, end, options) + * 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 + * @param {Object} [options] Available options: + * `animate: boolean | number` + * If true (default), the range is animated + * smoothly to the new window. + * If a number, the number is taken as duration + * for the animation. Default duration is 500 ms. */ - Item.prototype.setParent = function(parent) { - if (this.displayed) { - this.hide(); - this.parent = parent; - if (this.parent) { - this.show(); - } + Core.prototype.setWindow = function(start, end, options) { + var animate; + if (arguments.length == 1) { + var range = arguments[0]; + animate = (range.animate !== undefined) ? range.animate : true; + this.range.setRange(range.start, range.end, animate); } else { - this.parent = parent; + animate = (options && options.animate !== undefined) ? options.animate : true; + this.range.setRange(start, end, animate); } }; /** - * Check whether this item is visible inside given range - * @returns {{start: Number, end: Number}} range with a timestamp for start and end - * @returns {boolean} True if visible - */ - Item.prototype.isVisible = function(range) { - // Should be implemented by Item implementations - return false; - }; - - /** - * Show the Item in the DOM (when not already visible) - * @return {Boolean} changed + * Move the window such that given time is centered on screen. + * @param {Date | Number | String} time + * @param {Object} [options] Available options: + * `animate: boolean | number` + * If true (default), the range is animated + * smoothly to the new window. + * If a number, the number is taken as duration + * for the animation. Default duration is 500 ms. */ - Item.prototype.show = function() { - return false; - }; + Core.prototype.moveTo = function(time, options) { + var interval = this.range.end - this.range.start; + var t = util.convert(time, 'Date').valueOf(); - /** - * Hide the Item from the DOM (when visible) - * @return {Boolean} changed - */ - Item.prototype.hide = function() { - return false; - }; + var start = t - interval / 2; + var end = t + interval / 2; + var animate = (options && options.animate !== undefined) ? options.animate : true; - /** - * Repaint the item - */ - Item.prototype.redraw = function() { - // should be implemented by the item + this.range.setRange(start, end, animate); }; /** - * Reposition the Item horizontally + * Get the visible window + * @return {{start: Date, end: Date}} Visible range */ - Item.prototype.repositionX = function() { - // should be implemented by the item + Core.prototype.getWindow = function() { + var range = this.range.getRange(); + return { + start: new Date(range.start), + end: new Date(range.end) + }; }; /** - * Reposition the Item vertically + * Force a redraw. Can be overridden by implementations of Core */ - Item.prototype.repositionY = function() { - // should be implemented by the item + Core.prototype.redraw = function() { + this._redraw(); }; /** - * Repaint a delete button on the top right of the item when the item is selected - * @param {HTMLElement} anchor + * Redraw for internal use. Redraws all components. See also the public + * method redraw. * @protected */ - 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'; + Core.prototype._redraw = function() { + var resized = false; + var options = this.options; + var props = this.props; + var dom = this.dom; - Hammer(deleteButton, { - preventDefault: true - }).on('tap', function (event) { - me.parent.removeFromDataSet(me); - event.stopPropagation(); - }); + if (!dom) return; // when destroyed - 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; - } - }; + DateUtil.updateHiddenDates(this.body, this.options.hiddenDates); - /** - * Set HTML contents for the item - * @param {Element} element HTML element to fill with the contents - * @private - */ - Item.prototype._updateContents = function (element) { - var content; - if (this.options.template) { - var itemData = this.parent.itemSet.itemsData.get(this.id); // get a clone of the data from the dataset - content = this.options.template(itemData); + // update class names + if (options.orientation == 'top') { + util.addClassName(dom.root, 'top'); + util.removeClassName(dom.root, 'bottom'); } else { - content = this.data.content; + util.removeClassName(dom.root, 'top'); + util.addClassName(dom.root, 'bottom'); } - if(content !== this.content) { - // only replace the content when changed - if (content instanceof Element) { - element.innerHTML = ''; - element.appendChild(content); - } - else if (content != undefined) { - element.innerHTML = content; - } - else { - if (!(this.data.type == 'background' && this.data.content === undefined)) { - throw new Error('Property "content" missing in item ' + this.id); - } - } - - this.content = content; - } - }; + // 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, ''); - /** - * Set HTML contents for the item - * @param {Element} element HTML element to fill with the contents - * @private - */ - Item.prototype._updateTitle = function (element) { - if (this.data.title != null) { - element.title = this.data.title || ''; + // 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; + + // workaround for a bug in IE: the clientWidth of an element with + // a height:0px and overflow:hidden is not calculated and always has value 0 + if (dom.centerContainer.clientHeight === 0) { + props.border.left = props.border.top; + props.border.right = props.border.left; } - else { - element.removeAttribute('title'); + if (dom.root.clientHeight === 0) { + borderRootWidth = borderRootHeight; } - }; - /** - * Process dataAttributes timeline option and set as data- attributes on dom.content - * @param {Element} element HTML element to which the attributes will be attached - * @private - */ - Item.prototype._updateDataAttributes = function(element) { - if (this.options.dataAttributes && this.options.dataAttributes.length > 0) { - var attributes = []; + // 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; - if (Array.isArray(this.options.dataAttributes)) { - attributes = this.options.dataAttributes; - } - else if (this.options.dataAttributes == 'all') { - attributes = Object.keys(this.data); - } - else { - return; - } + // TODO: compensate borders when any of the panels is empty. - for (var i = 0; i < attributes.length; i++) { - var name = attributes[i]; - var value = this.data[name]; + // 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'); - if (value != null) { - element.setAttribute('data-' + name, value); - } - else { - element.removeAttribute('data-' + name); - } - } - } - }; + // 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; - /** - * Update custom styles of the element - * @param element - * @private - */ - Item.prototype._updateStyle = function(element) { - // remove old styles - if (this.style) { - util.removeCssText(element, this.style); - this.style = null; - } + // 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; - // append new styles - if (this.data.style) { - util.addCssText(element, this.data.style); - this.style = this.data.style; - } - }; + // 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'; - module.exports = Item; + 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 + props.border.left) + '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'; -/***/ }, -/* 32 */ -/***/ function(module, exports, __webpack_require__) { + // 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(); - var Hammer = __webpack_require__(45); - var Item = __webpack_require__(31); - var BackgroundGroup = __webpack_require__(26); - var RangeItem = __webpack_require__(35); + // 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'; - /** - * @constructor BackgroundItem - * @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 - */ - // TODO: implement support for the BackgroundItem just having a start, then being displayed as a sort of an annotation - function BackgroundItem (data, conversion, options) { - this.props = { - content: { - width: 0 - } - }; - this.overflow = false; // if contents can overflow (css styling), this flag is set to true + // 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; - // validate data - if (data) { - if (data.start == undefined) { - throw new Error('Property "start" missing in item ' + data.id); + // redraw all components + this.components.forEach(function (component) { + resized = component.redraw() || resized; + }); + if (resized) { + // keep repainting until all sizes are settled + var MAX_REDRAWS = 3; // maximum number of consecutive redraws + if (this.redrawCount < MAX_REDRAWS) { + this.redrawCount++; + this._redraw(); } - if (data.end == undefined) { - throw new Error('Property "end" missing in item ' + data.id); + else { + console.log('WARNING: infinite loop in redraw?'); } + this.redrawCount = 0; } - Item.call(this, data, conversion, options); - - this.emptyContent = false; - } - - BackgroundItem.prototype = new Item (null, null, null); + this.emit("finishedRedraw"); + }; - BackgroundItem.prototype.baseClassName = 'item background'; - BackgroundItem.prototype.stack = false; + // TODO: deprecated since version 1.1.0, remove some day + Core.prototype.repaint = function () { + throw new Error('Function repaint is deprecated. Use redraw instead.'); + }; /** - * 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 + * Set a current time. This can be used for example to ensure that a client's + * time is synchronized with a shared server time. + * Only applicable when option `showCurrentTime` is true. + * @param {Date | String | Number} time A Date, unix timestamp, or + * ISO date string. */ - BackgroundItem.prototype.isVisible = function(range) { - // determine visibility - return (this.data.start < range.end) && (this.data.end > range.start); + Core.prototype.setCurrentTime = function(time) { + if (!this.currentTime) { + throw new Error('Option showCurrentTime must be true'); + } + + this.currentTime.setCurrentTime(time); }; /** - * Repaint the item + * Get the current time. + * Only applicable when option `showCurrentTime` is true. + * @return {Date} Returns the current time. */ - BackgroundItem.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); - - // Note: we do NOT attach this item as attribute to the DOM, - // such that background items cannot be selected - //dom.box['timeline-item'] = this; - - this.dirty = true; - } - - // append DOM to parent DOM - if (!this.parent) { - throw new Error('Cannot redraw item: no parent attached'); - } - if (!dom.box.parentNode) { - var background = this.parent.dom.background; - if (!background) { - throw new Error('Cannot redraw item: parent has no background container element'); - } - background.appendChild(dom.box); + Core.prototype.getCurrentTime = function() { + if (!this.currentTime) { + throw new Error('Option showCurrentTime must be true'); } - this.displayed = true; - - // Update DOM when item is marked dirty. An item is marked dirty when: - // - the item is not yet rendered - // - the item's data is changed - // - the item is selected/deselected - if (this.dirty) { - this._updateContents(this.dom.content); - this._updateTitle(this.dom.content); - this._updateDataAttributes(this.dom.content); - this._updateStyle(this.dom.box); - - // update class - var className = (this.data.className ? (' ' + this.data.className) : '') + - (this.selected ? ' selected' : ''); - dom.box.className = this.baseClassName + className; - - // determine from css whether this box has overflow - this.overflow = window.getComputedStyle(dom.content).overflow !== 'hidden'; - - // recalculate size - this.props.content.width = this.dom.content.offsetWidth; - this.height = 0; // set height zero, so this item will be ignored when stacking items - this.dirty = false; - } + return this.currentTime.getCurrentTime(); }; /** - * Show the item in the DOM (when not already visible). The items DOM will - * be created when needed. + * 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 */ - BackgroundItem.prototype.show = RangeItem.prototype.show; + // TODO: move this function to Range + Core.prototype._toTime = function(x) { + return DateUtil.toTime(this, x, this.props.center.width); + }; /** - * Hide the item from the DOM (when visible) - * @return {Boolean} changed + * 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 */ - BackgroundItem.prototype.hide = RangeItem.prototype.hide; + // TODO: move this function to Range + Core.prototype._toGlobalTime = function(x) { + return DateUtil.toTime(this, x, this.props.root.width); + //var conversion = this.range.conversion(this.props.root.width); + //return new Date(x / conversion.scale + conversion.offset); + }; /** - * Reposition the item horizontally - * @Override + * 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 */ - BackgroundItem.prototype.repositionX = RangeItem.prototype.repositionX; + // TODO: move this function to Range + Core.prototype._toScreen = function(time) { + return DateUtil.toScreen(this, time, this.props.center.width); + }; + + /** - * Reposition the item vertically - * @Override + * 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 */ - BackgroundItem.prototype.repositionY = function(margin) { - var onTop = this.options.orientation === 'top'; - this.dom.content.style.top = onTop ? '' : '0'; - this.dom.content.style.bottom = onTop ? '0' : ''; - var height; + // TODO: move this function to Range + Core.prototype._toGlobalScreen = function(time) { + return DateUtil.toScreen(this, time, this.props.root.width); + //var conversion = this.range.conversion(this.props.root.width); + //return (time.valueOf() - conversion.offset) * conversion.scale; + }; - // special positioning for subgroups - if (this.data.subgroup !== undefined) { - var itemSubgroup = this.data.subgroup; - var subgroups = this.parent.subgroups; - var subgroupIndex = subgroups[itemSubgroup].index; - // if the orientation is top, we need to take the difference in height into account. - if (onTop == true) { - // the first subgroup will have to account for the distance from the top to the first item. - height = this.parent.subgroups[itemSubgroup].height + margin.item.vertical; - height += subgroupIndex == 0 ? margin.axis - 0.5*margin.item.vertical : 0; - var newTop = this.parent.top; - for (var subgroup in subgroups) { - if (subgroups.hasOwnProperty(subgroup)) { - if (subgroups[subgroup].visible == true && subgroups[subgroup].index < subgroupIndex) { - newTop += subgroups[subgroup].height + margin.item.vertical; - } - } - } - // the others will have to be offset downwards with this same distance. - newTop += subgroupIndex != 0 ? margin.axis - 0.5 * margin.item.vertical : 0; - this.dom.box.style.top = newTop + 'px'; - this.dom.box.style.bottom = ''; - } - // and when the orientation is bottom: - else { - var newTop = this.parent.top; - for (var subgroup in subgroups) { - if (subgroups.hasOwnProperty(subgroup)) { - if (subgroups[subgroup].visible == true && subgroups[subgroup].index > subgroupIndex) { - newTop += subgroups[subgroup].height + margin.item.vertical; - } - } - } - height = this.parent.subgroups[itemSubgroup].height + margin.item.vertical; - this.dom.box.style.top = newTop + 'px'; - this.dom.box.style.bottom = ''; - } + /** + * Initialize watching when option autoResize is true + * @private + */ + Core.prototype._initAutoResize = function () { + if (this.options.autoResize == true) { + this._startAutoResize(); } - // and in the case of no subgroups: else { - // we want backgrounds with groups to only show in groups. - if (this.parent instanceof BackgroundGroup) { - // if the item is not in a group: - height = Math.max(this.parent.height, - this.parent.itemSet.body.domProps.center.height, - this.parent.itemSet.body.domProps.centerContainer.height); - this.dom.box.style.top = onTop ? '0' : ''; - this.dom.box.style.bottom = onTop ? '' : '0'; - } - else { - height = this.parent.height; - // same alignment for items when orientation is top or bottom - this.dom.box.style.top = this.parent.top + 'px'; - this.dom.box.style.bottom = ''; - } + this._stopAutoResize(); } - this.dom.box.style.height = height + 'px'; }; - module.exports = BackgroundItem; + /** + * 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(); -/***/ }, -/* 33 */ -/***/ function(module, exports, __webpack_require__) { + this._onResize = function() { + if (me.options.autoResize != true) { + // stop watching when the option autoResize is changed to false + me._stopAutoResize(); + return; + } - var Item = __webpack_require__(31); - var util = __webpack_require__(1); + if (me.dom.root) { + // check whether the frame is resized + // Note: we compare offsetWidth here, not clientWidth. For some reason, + // IE does not restore the clientWidth from 0 to the actual width after + // changing the timeline's container display style from none to visible + if ((me.dom.root.offsetWidth != me.props.lastWidth) || + (me.dom.root.offsetHeight != me.props.lastHeight)) { + me.props.lastWidth = me.dom.root.offsetWidth; + me.props.lastHeight = me.dom.root.offsetHeight; - /** - * @constructor BoxItem - * @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 BoxItem (data, conversion, options) { - this.props = { - dot: { - width: 0, - height: 0 - }, - line: { - width: 0, - height: 0 + me.emit('change'); + } } }; - // validate data - if (data) { - if (data.start == undefined) { - throw new Error('Property "start" missing in item ' + data); - } - } - - Item.call(this, data, conversion, options); - } + // add event listener to window resize + util.addEventListener(window, 'resize', this._onResize); - BoxItem.prototype = new Item (null, null, null); + this.watchTimer = setInterval(this._onResize, 1000); + }; /** - * 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 + * Stop watching for a resize of the frame. + * @private */ - BoxItem.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); + Core.prototype._stopAutoResize = function () { + if (this.watchTimer) { + clearInterval(this.watchTimer); + this.watchTimer = undefined; + } + + // remove event listener on window.resize + util.removeEventListener(window, 'resize', this._onResize); + this._onResize = null; }; /** - * Repaint the item + * Start moving the timeline vertically + * @param {Event} event + * @private */ - BoxItem.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; - - this.dirty = true; - } - - // append DOM to parent DOM - if (!this.parent) { - throw new Error('Cannot redraw item: no parent attached'); - } - if (!dom.box.parentNode) { - var foreground = this.parent.dom.foreground; - if (!foreground) throw new Error('Cannot redraw item: parent has no foreground container element'); - foreground.appendChild(dom.box); - } - if (!dom.line.parentNode) { - var background = this.parent.dom.background; - if (!background) throw new Error('Cannot redraw item: 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 item: parent has no axis container element'); - axis.appendChild(dom.dot); - } - this.displayed = true; - - // Update DOM when item is marked dirty. An item is marked dirty when: - // - the item is not yet rendered - // - the item's data is changed - // - the item is selected/deselected - if (this.dirty) { - this._updateContents(this.dom.content); - this._updateTitle(this.dom.box); - this._updateDataAttributes(this.dom.box); - this._updateStyle(this.dom.box); - - // update class - var className = (this.data.className? ' ' + this.data.className : '') + - (this.selected ? ' selected' : ''); - dom.box.className = 'item box' + className; - dom.line.className = 'item line' + className; - dom.dot.className = 'item dot' + className; - - // recalculate size - this.props.dot.height = dom.dot.offsetHeight; - this.props.dot.width = dom.dot.offsetWidth; - this.props.line.width = dom.line.offsetWidth; - this.width = dom.box.offsetWidth; - this.height = dom.box.offsetHeight; - - this.dirty = false; - } + Core.prototype._onTouch = function (event) { + this.touch.allowDragging = true; + }; - this._repaintDeleteButton(dom.box); + /** + * Start moving the timeline vertically + * @param {Event} event + * @private + */ + Core.prototype._onPinch = function (event) { + this.touch.allowDragging = false; }; /** - * Show the item in the DOM (when not already displayed). The items DOM will - * be created when needed. + * Start moving the timeline vertically + * @param {Event} event + * @private */ - BoxItem.prototype.show = function() { - if (!this.displayed) { - this.redraw(); - } + Core.prototype._onDragStart = function (event) { + this.touch.initialScrollTop = this.props.scrollTop; }; /** - * Hide the item from the DOM (when visible) + * Move the timeline vertically + * @param {Event} event + * @private */ - BoxItem.prototype.hide = function() { - if (this.displayed) { - var dom = this.dom; + Core.prototype._onDrag = function (event) { + // refuse to drag when we where pinching to prevent the timeline make a jump + // when releasing the fingers in opposite order from the touch screen + if (!this.touch.allowDragging) return; - if (dom.box.parentNode) dom.box.parentNode.removeChild(dom.box); - if (dom.line.parentNode) dom.line.parentNode.removeChild(dom.line); - if (dom.dot.parentNode) dom.dot.parentNode.removeChild(dom.dot); + var delta = event.gesture.deltaY; - this.top = null; - this.left = null; + var oldScrollTop = this._getScrollTop(); + var newScrollTop = this._setScrollTop(this.touch.initialScrollTop + delta); - this.displayed = false; + + if (newScrollTop != oldScrollTop) { + this._redraw(); // TODO: this causes two redraws when dragging, the other is triggered by rangechange already + this.emit("verticalDrag"); } }; /** - * Reposition the item horizontally - * @Override + * Apply a scrollTop + * @param {Number} scrollTop + * @returns {Number} scrollTop Returns the applied scrollTop + * @private */ - BoxItem.prototype.repositionX = function() { - var start = this.conversion.toScreen(this.data.start); - var align = this.options.align; - var left; - var box = this.dom.box; - var line = this.dom.line; - var dot = this.dom.dot; + Core.prototype._setScrollTop = function (scrollTop) { + this.props.scrollTop = scrollTop; + this._updateScrollTop(); + return this.props.scrollTop; + }; - // 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; + /** + * 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; } - // reposition box - box.style.left = this.left + 'px'; - - // reposition line - line.style.left = (start - this.props.line.width / 2) + 'px'; + // 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; - // reposition dot - dot.style.left = (start - this.props.dot.width / 2) + 'px'; + return this.props.scrollTop; }; /** - * Reposition the item vertically - * @Override + * Get the current scrollTop + * @returns {number} scrollTop + * @private */ - BoxItem.prototype.repositionY = function() { - var orientation = this.options.orientation; - var box = this.dom.box; - var line = this.dom.line; - var 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 = ''; - } - 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'; - } - - dot.style.top = (-this.props.dot.height / 2) + 'px'; + Core.prototype._getScrollTop = function () { + return this.props.scrollTop; }; - module.exports = BoxItem; + module.exports = Core; /***/ }, -/* 34 */ +/* 26 */ /***/ function(module, exports, __webpack_require__) { - var Item = __webpack_require__(31); + var Hammer = __webpack_require__(19); + var util = __webpack_require__(1); + var DataSet = __webpack_require__(7); + var DataView = __webpack_require__(9); + var TimeStep = __webpack_require__(27); + var Component = __webpack_require__(23); + var Group = __webpack_require__(28); + var BackgroundGroup = __webpack_require__(32); + var BoxItem = __webpack_require__(33); + var PointItem = __webpack_require__(34); + var RangeItem = __webpack_require__(30); + var BackgroundItem = __webpack_require__(35); + + + var UNGROUPED = '__ungrouped__'; // reserved group id for ungrouped items + var BACKGROUND = '__background__'; // reserved group id for background items without group /** - * @constructor PointItem - * @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 + * 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 PointItem (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); - } - } + function ItemSet(body, options) { + this.body = body; - Item.call(this, data, conversion, options); - } + this.defaultOptions = { + type: null, // 'box', 'point', 'range', 'background' + orientation: 'bottom', // 'top' or 'bottom' + align: 'auto', // alignment of box items + stack: true, + groupOrder: null, - PointItem.prototype = new Item (null, null, null); + selectable: true, + editable: { + updateTime: false, + updateGroup: false, + add: false, + remove: false + }, - /** - * 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 - */ - PointItem.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); - }; + snap: TimeStep.snap, - /** - * Repaint the item - */ - PointItem.prototype.redraw = function() { - var dom = this.dom; - if (!dom) { - // create DOM - this.dom = {}; - dom = this.dom; + onAdd: function (item, callback) { + callback(item); + }, + onUpdate: function (item, callback) { + callback(item); + }, + onMove: function (item, callback) { + callback(item); + }, + onRemove: function (item, callback) { + callback(item); + }, + onMoving: function (item, callback) { + callback(item); + }, - // background box - dom.point = document.createElement('div'); - // className is updated in redraw() + margin: { + item: { + horizontal: 10, + vertical: 10 + }, + axis: 20 + }, + padding: 5 + }; - // contents box, right from the dot - dom.content = document.createElement('div'); - dom.content.className = 'content'; - dom.point.appendChild(dom.content); + // options is shared by this ItemSet and all its items + this.options = util.extend({}, this.defaultOptions); - // dot at start - dom.dot = document.createElement('div'); - dom.point.appendChild(dom.dot); + // options for getting items from the DataSet with the correct type + this.itemOptions = { + type: {start: 'Date', end: 'Date'} + }; - // attach this item as attribute - dom.point['timeline-item'] = this; + this.conversion = { + toScreen: body.util.toScreen, + toTime: body.util.toTime + }; + this.dom = {}; + this.props = {}; + this.hammer = null; - this.dirty = true; - } + var me = this; + this.itemsData = null; // DataSet + this.groupsData = null; // DataSet - // 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 item: parent has no foreground container element'); + // 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); } - foreground.appendChild(dom.point); - } - this.displayed = true; + }; - // Update DOM when item is marked dirty. An item is marked dirty when: - // - the item is not yet rendered - // - the item's data is changed - // - the item is selected/deselected - if (this.dirty) { - this._updateContents(this.dom.content); - this._updateTitle(this.dom.point); - this._updateDataAttributes(this.dom.point); - this._updateStyle(this.dom.point); + // 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); + } + }; - // update class - var className = (this.data.className? ' ' + this.data.className : '') + - (this.selected ? ' selected' : ''); - dom.point.className = 'item point' + className; - dom.dot.className = 'item dot' + className; + this.items = {}; // object with an Item for every data item + this.groups = {}; // Group object for every group + this.groupIds = []; - // recalculate size - 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; + this.selection = []; // list with the ids of all selected nodes + this.stackDirty = true; // if true, all items will be restacked on next redraw - // resize contents - dom.content.style.marginLeft = 2 * this.props.dot.width + 'px'; - //dom.content.style.marginRight = ... + 'px'; // TODO: margin right + this.touchParams = {}; // stores properties while dragging + // create the HTML DOM - dom.dot.style.top = ((this.height - this.props.dot.height) / 2) + 'px'; - dom.dot.style.left = (this.props.dot.width / 2) + 'px'; + this._create(); - this.dirty = false; - } + this.setOptions(options); + } - this._repaintDeleteButton(dom.point); - }; + ItemSet.prototype = new Component(); - /** - * Show the item in the DOM (when not already visible). The items DOM will - * be created when needed. - */ - PointItem.prototype.show = function() { - if (!this.displayed) { - this.redraw(); - } + // available item types will be registered here + ItemSet.types = { + background: BackgroundItem, + box: BoxItem, + range: RangeItem, + point: PointItem }; /** - * Hide the item from the DOM (when visible) + * Create the HTML DOM for the ItemSet */ - PointItem.prototype.hide = function() { - if (this.displayed) { - if (this.dom.point.parentNode) { - this.dom.point.parentNode.removeChild(this.dom.point); - } + ItemSet.prototype._create = function(){ + var frame = document.createElement('div'); + frame.className = 'itemset'; + frame['timeline-itemset'] = this; + this.dom.frame = frame; - this.top = null; - this.left = null; + // create background panel + var background = document.createElement('div'); + background.className = 'background'; + frame.appendChild(background); + this.dom.background = background; - this.displayed = false; - } - }; + // create foreground panel + var foreground = document.createElement('div'); + foreground.className = 'foreground'; + frame.appendChild(foreground); + this.dom.foreground = foreground; - /** - * Reposition the item horizontally - * @Override - */ - PointItem.prototype.repositionX = function() { - var start = this.conversion.toScreen(this.data.start); + // create axis panel + var axis = document.createElement('div'); + axis.className = 'axis'; + this.dom.axis = axis; - this.left = start - this.props.dot.width; + // create labelset + var labelSet = document.createElement('div'); + labelSet.className = 'labelset'; + this.dom.labelSet = labelSet; - // reposition point - this.dom.point.style.left = this.left + 'px'; - }; + // create ungrouped Group + this._updateUngrouped(); - /** - * Reposition the item vertically - * @Override - */ - PointItem.prototype.repositionY = function() { - var orientation = this.options.orientation, - point = this.dom.point; + // create background Group + var backgroundGroup = new BackgroundGroup(BACKGROUND, null, this); + backgroundGroup.show(); + this.groups[BACKGROUND] = backgroundGroup; - if (orientation == 'top') { - point.style.top = this.top + 'px'; - } - else { - point.style.top = (this.parent.height - this.top - this.height) + 'px'; - } - }; + // 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, { + preventDefault: true + }); - module.exports = PointItem; + // 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)); + // single select (or unselect) when tapping an item + this.hammer.on('tap', this._onSelectItem.bind(this)); -/***/ }, -/* 35 */ -/***/ function(module, exports, __webpack_require__) { + // multi select when holding mouse/touch, or on ctrl+click + this.hammer.on('hold', this._onMultiSelectItem.bind(this)); - var Hammer = __webpack_require__(45); - var Item = __webpack_require__(31); + // add item on doubletap + this.hammer.on('doubletap', this._onAddItem.bind(this)); + + // attach to the DOM + this.show(); + }; /** - * @constructor RangeItem - * @extends Item - * @param {Object} data Object containing parameters start, end - * content, className. - * @param {{toScreen: function, toTime: function}} conversion - * Conversion functions from time to screen and vice versa - * @param {Object} [options] Configuration options - * // TODO: describe options + * 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', 'range', or 'background'. + * The default style can be overwritten by + * individual items. + * {String} align + * Alignment for the items, only applicable for + * BoxItem. 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. */ - function RangeItem (data, conversion, options) { - this.props = { - content: { - width: 0 - } - }; - this.overflow = false; // if contents can overflow (css styling), this flag is set to true + ItemSet.prototype.setOptions = function(options) { + if (options) { + // copy all options that we know + var fields = ['type', 'align', 'orientation', 'padding', 'stack', 'selectable', 'groupOrder', 'dataAttributes', 'template','hide', 'snap']; + util.selectiveExtend(fields, this.options, options); - // validate data - if (data) { - if (data.start == undefined) { - throw new Error('Property "start" missing in item ' + data.id); - } - if (data.end == undefined) { - throw new Error('Property "end" missing in item ' + data.id); + 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); + } + } + } } - } - Item.call(this, data, conversion, options); - } + 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); + } + } - RangeItem.prototype = new Item (null, null, null); + // callback functions + var addCallback = (function (name) { + var fn = options[name]; + if (fn) { + 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', 'onMoving'].forEach(addCallback); - RangeItem.prototype.baseClassName = 'item range'; + // force the itemSet to refresh: options like orientation and margins may be changed + this.markDirty(); + } + }; /** - * 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 + * Mark the ItemSet dirty so it will refresh everything with next redraw. + * Optionally, all items can be marked as dirty and be refreshed. + * @param {{refreshItems: boolean}} [options] */ - RangeItem.prototype.isVisible = function(range) { - // determine visibility - return (this.data.start < range.end) && (this.data.end > range.start); + ItemSet.prototype.markDirty = function(options) { + this.groupIds = []; + this.stackDirty = true; + + if (options && options.refreshItems) { + util.forEach(this.items, function (item) { + item.dirty = true; + if (item.displayed) item.redraw(); + }); + } }; /** - * Repaint the item + * Destroy the ItemSet */ - RangeItem.prototype.redraw = function() { - var dom = this.dom; - if (!dom) { - // create DOM - this.dom = {}; - dom = this.dom; + ItemSet.prototype.destroy = function() { + this.hide(); + this.setItems(null); + this.setGroups(null); - // background box - dom.box = document.createElement('div'); - // className is updated in redraw() + this.hammer = null; - // contents box - dom.content = document.createElement('div'); - dom.content.className = 'content'; - dom.box.appendChild(dom.content); + this.body = null; + this.conversion = null; + }; - // attach this item as attribute - dom.box['timeline-item'] = this; + /** + * 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); + } - this.dirty = true; + // remove the axis with dots + if (this.dom.axis.parentNode) { + this.dom.axis.parentNode.removeChild(this.dom.axis); } - // append DOM to parent DOM - if (!this.parent) { - throw new Error('Cannot redraw item: no parent attached'); + // remove the labelset containing all group labels + if (this.dom.labelSet.parentNode) { + this.dom.labelSet.parentNode.removeChild(this.dom.labelSet); } - if (!dom.box.parentNode) { - var foreground = this.parent.dom.foreground; - if (!foreground) { - throw new Error('Cannot redraw item: parent has no foreground container element'); - } - foreground.appendChild(dom.box); + }; + + /** + * 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); } - this.displayed = true; - // Update DOM when item is marked dirty. An item is marked dirty when: - // - the item is not yet rendered - // - the item's data is changed - // - the item is selected/deselected - if (this.dirty) { - this._updateContents(this.dom.content); - this._updateTitle(this.dom.box); - this._updateDataAttributes(this.dom.box); - this._updateStyle(this.dom.box); + // show axis with dots + if (!this.dom.axis.parentNode) { + this.body.dom.backgroundVertical.appendChild(this.dom.axis); + } - // update class - var className = (this.data.className ? (' ' + this.data.className) : '') + - (this.selected ? ' selected' : ''); - dom.box.className = this.baseClassName + className; + // show labelset containing labels + if (!this.dom.labelSet.parentNode) { + this.body.dom.left.appendChild(this.dom.labelSet); + } + }; - // determine from css whether this box has overflow - this.overflow = window.getComputedStyle(dom.content).overflow !== 'hidden'; + /** + * Set selected items by their id. Replaces the current selection + * Unknown id's are silently ignored. + * @param {string[] | string} [ids] An array with zero or more id's of the items to be + * selected, or a single item id. If ids is undefined + * or an empty array, all items will be unselected. + */ + ItemSet.prototype.setSelection = function(ids) { + var i, ii, id, item; - // recalculate size - // turn off max-width to be able to calculate the real width - // this causes an extra browser repaint/reflow, but so be it - this.dom.content.style.maxWidth = 'none'; - this.props.content.width = this.dom.content.offsetWidth; - this.height = this.dom.box.offsetHeight; - this.dom.content.style.maxWidth = ''; + if (ids == undefined) ids = []; + if (!Array.isArray(ids)) ids = [ids]; - this.dirty = false; + // 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(); } - this._repaintDeleteButton(dom.box); - this._repaintDragLeft(); - this._repaintDragRight(); + // 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(); + } + } }; /** - * Show the item in the DOM (when not already visible). The items DOM will - * be created when needed. + * Get the selected items by their id + * @return {Array} ids The ids of the selected items */ - RangeItem.prototype.show = function() { - if (!this.displayed) { - this.redraw(); - } + ItemSet.prototype.getSelection = function() { + return this.selection.concat([]); }; /** - * Hide the item from the DOM (when visible) - * @return {Boolean} changed + * Get the id's of the currently visible items. + * @returns {Array} The ids of the visible items */ - RangeItem.prototype.hide = function() { - if (this.displayed) { - var box = this.dom.box; + 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); - if (box.parentNode) { - box.parentNode.removeChild(box); + var ids = []; + for (var groupId in this.groups) { + if (this.groups.hasOwnProperty(groupId)) { + var group = this.groups[groupId]; + var rawVisibleItems = group.visibleItems; + + // filter the "raw" set with visibleItems into a set which is really + // visible by pixels + for (var i = 0; i < rawVisibleItems.length; i++) { + var item = rawVisibleItems[i]; + // TODO: also check whether visible vertically + if ((item.left < right) && (item.left + item.width > left)) { + ids.push(item.id); + } + } } + } - this.top = null; - this.left = null; + return ids; + }; - this.displayed = false; + /** + * 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; + } } }; /** - * Reposition the item horizontally - * @Override + * Repaint the component + * @return {boolean} Returns true if the component is resized */ - RangeItem.prototype.repositionX = function() { - var parentWidth = this.parent.width; - var start = this.conversion.toScreen(this.data.start); - var end = this.conversion.toScreen(this.data.end); - var contentLeft; - var contentWidth; + 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; - // limit the width of the this, as browsers cannot draw very wide divs - if (start < -parentWidth) { - start = -parentWidth; - } - if (end > 2 * parentWidth) { - end = 2 * parentWidth; - } - var boxWidth = Math.max(end - start, 1); + // recalculate absolute position (before redrawing groups) + this.props.top = this.body.domProps.top.height + this.body.domProps.border.top; + this.props.left = this.body.domProps.left.width + this.body.domProps.border.left; - if (this.overflow) { - this.left = start; - this.width = boxWidth + this.props.content.width; - contentWidth = this.props.content.width; + // update class name + frame.className = 'itemset' + (editable ? ' editable' : ''); - // Note: The calculation of width is an optimistic calculation, giving - // a width which will not change when moving the Timeline - // So no re-stacking needed, which is nicer for the eye; - } - else { - this.left = start; - this.width = boxWidth; - contentWidth = Math.min(end - start - 2 * this.options.padding, this.props.content.width); - } + // reorder the groups (if needed) + resized = this._orderGroups() || resized; - this.dom.box.style.left = this.left + 'px'; - this.dom.box.style.width = boxWidth + 'px'; + // 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; - switch (this.options.align) { - case 'left': - this.dom.content.style.left = '0'; - break; + var restack = this.stackDirty; + var firstGroup = this._firstGroup(); + var firstMargin = { + item: margin.item, + axis: margin.axis + }; + var nonFirstMargin = { + item: margin.item, + axis: margin.item.vertical / 2 + }; + var height = 0; + var minHeight = margin.axis + margin.item.vertical; - case 'right': - this.dom.content.style.left = Math.max((boxWidth - contentWidth - 2 * this.options.padding), 0) + 'px'; - break; + // redraw the background group + this.groups[BACKGROUND].redraw(range, nonFirstMargin, restack); - case 'center': - this.dom.content.style.left = Math.max((boxWidth - contentWidth - 2 * this.options.padding) / 2, 0) + 'px'; - break; + // redraw all regular groups + 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; - default: // 'auto' - // when range exceeds left of the window, position the contents at the left of the visible area - if (this.overflow) { - if (end > 0) { - contentLeft = Math.max(-start, 0); - } - else { - contentLeft = -contentWidth; // ensure it's not visible anymore - } - } - else { - if (start < 0) { - contentLeft = Math.min(-start, - (end - start - contentWidth - 2 * this.options.padding)); - // TODO: remove the need for options.padding. it's terrible. - } - else { - contentLeft = 0; - } - } - this.dom.content.style.left = contentLeft + 'px'; - } + // update frame height + frame.style.height = asSize(height); + + // calculate actual size + this.props.width = frame.offsetWidth; + this.props.height = height; + + // 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 = '0'; + + // check if this component is resized + resized = this._isResized() || resized; + + return resized; }; /** - * Reposition the item vertically - * @Override + * Get the first group, aligned with the axis + * @return {Group | null} firstGroup + * @private */ - RangeItem.prototype.repositionY = function() { - var orientation = this.options.orientation, - box = this.dom.box; + 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]; - if (orientation == 'top') { - box.style.top = this.top + 'px'; - } - else { - box.style.top = (this.parent.height - this.top - this.height) + 'px'; - } + return firstGroup || null; }; /** - * Repaint a drag area on the left side of the range when the range is selected + * Create or delete the group holding all ungrouped items. This group is used when + * there are no groups specified. * @protected */ - RangeItem.prototype._repaintDragLeft = function () { - if (this.selected && this.options.editable.updateTime && !this.dom.dragLeft) { - // create and show drag area - var dragLeft = document.createElement('div'); - dragLeft.className = 'drag-left'; - dragLeft.dragLeftItem = this; + ItemSet.prototype._updateUngrouped = function() { + var ungrouped = this.groups[UNGROUPED]; + var background = this.groups[BACKGROUND]; + var item, itemId; - // TODO: this should be redundant? - Hammer(dragLeft, { - preventDefault: true - }).on('drag', function () { - //console.log('drag left') - }); + if (this.groupsData) { + // remove the group holding all ungrouped items + if (ungrouped) { + ungrouped.hide(); + delete this.groups[UNGROUPED]; - this.dom.box.appendChild(dragLeft); - this.dom.dragLeft = dragLeft; + for (itemId in this.items) { + if (this.items.hasOwnProperty(itemId)) { + item = this.items[itemId]; + item.parent && item.parent.remove(item); + var groupId = this._getGroupId(item.data); + var group = this.groups[groupId]; + group && group.add(item) || item.hide(); + } + } + } } - else if (!this.selected && this.dom.dragLeft) { - // delete drag area - if (this.dom.dragLeft.parentNode) { - this.dom.dragLeft.parentNode.removeChild(this.dom.dragLeft); + 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 (itemId in this.items) { + if (this.items.hasOwnProperty(itemId)) { + item = this.items[itemId]; + ungrouped.add(item); + } + } + + ungrouped.show(); } - this.dom.dragLeft = null; } }; /** - * Repaint a drag area on the right side of the range when the range is selected - * @protected + * Get the element for the labelset + * @return {HTMLElement} labelSet */ - RangeItem.prototype._repaintDragRight = function () { - if (this.selected && this.options.editable.updateTime && !this.dom.dragRight) { - // create and show drag area - var dragRight = document.createElement('div'); - dragRight.className = 'drag-right'; - dragRight.dragRightItem = this; + ItemSet.prototype.getLabelSet = function() { + return this.dom.labelSet; + }; - // TODO: this should be redundant? - Hammer(dragRight, { - preventDefault: true - }).on('drag', function () { - //console.log('drag right') - }); + /** + * Set items + * @param {vis.DataSet | null} items + */ + ItemSet.prototype.setItems = function(items) { + var me = this, + ids, + oldItemsData = this.itemsData; - this.dom.box.appendChild(dragRight); - this.dom.dragRight = dragRight; + // replace the dataset + if (!items) { + this.itemsData = null; } - 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; + else if (items instanceof DataSet || items instanceof DataView) { + this.itemsData = items; + } + else { + throw new TypeError('Data must be an instance of DataSet or DataView'); } - }; - module.exports = RangeItem; + 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); + } -/***/ }, -/* 36 */ -/***/ function(module, exports, __webpack_require__) { + if (this.itemsData) { + // subscribe to new dataset + var id = this.id; + util.forEach(this.itemListeners, function (callback, event) { + me.itemsData.on(event, callback, id); + }); - var Emitter = __webpack_require__(56); - var Hammer = __webpack_require__(45); - var keycharm = __webpack_require__(58); - var util = __webpack_require__(1); - var hammerUtil = __webpack_require__(47); - var DataSet = __webpack_require__(3); - var DataView = __webpack_require__(4); - var dotparser = __webpack_require__(42); - var gephiParser = __webpack_require__(43); - var Groups = __webpack_require__(38); - var Images = __webpack_require__(39); - var Node = __webpack_require__(40); - var Edge = __webpack_require__(37); - var Popup = __webpack_require__(41); - var MixinLoader = __webpack_require__(54); - var Activator = __webpack_require__(55); - var locales = __webpack_require__(49); + // add all new items + ids = this.itemsData.getIds(); + this._onAdd(ids); - // Load custom shapes into CanvasRenderingContext2D - __webpack_require__(50); + // update the group holding all ungrouped items + this._updateUngrouped(); + } + }; /** - * @constructor Network - * Create a network visualization, displaying nodes and edges. - * - * @param {Element} container The DOM element in which the Network will - * be created. Normally a div element. - * @param {Object} data An object containing parameters - * {Array} nodes - * {Array} edges - * @param {Object} options Options + * Get the current items + * @returns {vis.DataSet | null} */ - function Network (container, data, options) { - if (!(this instanceof Network)) { - throw new SyntaxError('Constructor must be called with the new operator'); - } + ItemSet.prototype.getItems = function() { + return this.itemsData; + }; - this._determineBrowserMethod(); - this._initializeMixinLoaders(); + /** + * Set groups + * @param {vis.DataSet} groups + */ + ItemSet.prototype.setGroups = function(groups) { + var me = this, + ids; - // create variables and set default values - this.containerElement = container; + // unsubscribe from current dataset + if (this.groupsData) { + util.forEach(this.groupListeners, function (callback, event) { + me.groupsData.unsubscribe(event, callback); + }); - // render and calculation settings - this.renderRefreshRate = 60; // hz (fps) - this.renderTimestep = 1000 / this.renderRefreshRate; // ms -- saves calculation later on - this.renderTime = 0; // measured time it takes to render a frame - this.physicsTime = 0; // measured time it takes to render a frame - this.runDoubleSpeed = false; - this.physicsDiscreteStepsize = 0.50; // discrete stepsize of the simulation + // remove all drawn groups + ids = this.groupsData.getIds(); + this.groupsData = null; + this._onRemoveGroups(ids); // note: this will cause a redraw + } - this.initializing = true; + // replace the dataset + if (!groups) { + this.groupsData = null; + } + else if (groups instanceof DataSet || groups instanceof DataView) { + this.groupsData = groups; + } + else { + throw new TypeError('Data must be an instance of DataSet or DataView'); + } - this.triggerFunctions = {add:null,edit:null,editEdge:null,connect:null,del:null}; + if (this.groupsData) { + // subscribe to new dataset + var id = this.id; + util.forEach(this.groupListeners, function (callback, event) { + me.groupsData.on(event, callback, id); + }); - var customScalingFunction = function (min,max,total,value) { - if (max == min) { - return 0.5; - } - else { - var scale = 1 / (max - min); - return Math.max(0,(value - min)*scale); - } - }; - // set constant values - this.defaultOptions = { - nodes: { - customScalingFunction: customScalingFunction, - mass: 1, - radiusMin: 10, - radiusMax: 30, - radius: 10, - shape: 'ellipse', - image: undefined, - widthMin: 16, // px - widthMax: 64, // px - fontColor: 'black', - fontSize: 14, // px - fontFace: 'verdana', - fontFill: undefined, - fontStrokeWidth: 0, // px - fontStrokeColor: '#ffffff', - fontDrawThreshold: 3, - scaleFontWithValue: false, - fontSizeMin: 14, - fontSizeMax: 30, - fontSizeMaxVisible: 30, - level: -1, - color: { - border: '#2B7CE9', - background: '#97C2FC', - highlight: { - border: '#2B7CE9', - background: '#D2E5FF' - }, - hover: { - border: '#2B7CE9', - background: '#D2E5FF' - } - }, - group: undefined, - borderWidth: 1, - borderWidthSelected: undefined - }, - edges: { - customScalingFunction: customScalingFunction, - widthMin: 1, // - widthMax: 15,// - width: 1, - widthSelectionMultiplier: 2, - hoverWidth: 1.5, - style: 'line', - color: { - color:'#848484', - highlight:'#848484', - hover: '#848484' - }, - opacity:1.0, - fontColor: '#343434', - fontSize: 14, // px - fontFace: 'arial', - fontFill: 'white', - fontStrokeWidth: 0, // px - fontStrokeColor: 'white', - labelAlignment:'horizontal', - arrowScaleFactor: 1, - dash: { - length: 10, - gap: 5, - altLength: undefined - }, - inheritColor: "from", // to, from, false, true (== from) - useGradients: false // release in 4.0 - }, - configurePhysics:false, - physics: { - barnesHut: { - enabled: true, - thetaInverted: 1 / 0.5, // 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, // used for normalization of the cluster levels - clusterByZoom: true // enable clustering through zooming in and out - }, - navigation: { - enabled: false - }, - keyboard: { - enabled: false, - speed: {x: 10, y: 10, zoom: 0.02}, - bindToWindow: true - }, - dataManipulation: { - enabled: false, - initiallyVisible: false - }, - hierarchicalLayout: { - enabled:false, - levelSeparation: 150, - nodeSpacing: 100, - direction: "UD", // UD, DU, LR, RL - layout: "hubsize" // hubsize, directed - }, - freezeForStabilization: false, - smoothCurves: { - enabled: true, - dynamic: true, - type: "continuous", - roundness: 0.5 - }, - maxVelocity: 50, - minVelocity: 0.1, // px/s - stabilize: true, // stabilize before displaying the network - stabilizationIterations: 1000, // maximum number of iteration to stabilize - zoomExtentOnStabilize: true, - locale: 'en', - locales: locales, - tooltip: { - delay: 300, - fontColor: 'black', - fontSize: 14, // px - fontFace: 'verdana', - color: { - border: '#666', - background: '#FFFFC6' - } - }, - dragNetwork: true, - dragNodes: true, - zoomable: true, - hover: false, - hideEdgesOnDrag: false, - hideNodesOnDrag: false, - width : '100%', - height : '100%', - selectable: true, - useDefaultGroups: true - }; - this.constants = util.extend({}, this.defaultOptions); - this.pixelRatio = 1; - - - this.hoverObj = {nodes:{},edges:{}}; - this.controlNodesActive = false; - this.navigationHammers = {existing:[], _new: []}; + // draw all ms + ids = this.groupsData.getIds(); + this._onAddGroups(ids); + } - // animation properties - this.animationSpeed = 1/this.renderRefreshRate; - this.animationEasingFunction = "easeInOutQuint"; - this.animating = false; - this.easingTime = 0; - this.sourceScale = 0; - this.targetScale = 0; - this.sourceTranslation = 0; - this.targetTranslation = 0; - this.lockedOnNodeId = null; - this.lockedOnNodeOffset = null; - this.touchTime = 0; - this.redrawRequested = false; + // update the group holding all ungrouped items + this._updateUngrouped(); - // Node variables - var network = this; - this.groups = new Groups(); // object with groups - this.images = new Images(); // object with images - this.images.setOnloadCallback(function (status) { - network._requestRedraw(); - }); + // update the order of all items in each group + this._order(); - // keyboard navigation variables - this.xIncrement = 0; - this.yIncrement = 0; - this.zoomIncrement = 0; + this.body.emitter.emit('change', {queue: true}); + }; - // 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(); + /** + * Get the current groups + * @returns {vis.DataSet | null} groups + */ + ItemSet.prototype.getGroups = function() { + return this.groupsData; + }; + /** + * 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(); - // apply options - this._setTranslation(this.frame.clientWidth / 2, this.frame.clientHeight / 2); - this._setScale(1); - this.setOptions(options); + 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); + } + }); + } + }; - // other vars - this.freezeSimulationEnabled = false;// freeze the simulation - this.cachedFunctions = {}; - this.startedStabilization = false; - this.stabilized = false; - this.stabilizationIterations = null; - this.draggingNodes = false; + /** + * Get the time of an item based on it's data and options.type + * @param {Object} itemData + * @returns {string} Returns the type + * @private + */ + ItemSet.prototype._getType = function (itemData) { + return itemData.type || this.options.type || (itemData.end ? 'range' : 'box'); + }; - // 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 - // 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 + /** + * Get the group id for an item + * @param {Object} itemData + * @returns {string} Returns the groupId + * @private + */ + ItemSet.prototype._getGroupId = function (itemData) { + var type = this._getType(itemData); + if (type == 'background' && itemData.group == undefined) { + return BACKGROUND; + } + else { + return this.groupsData ? itemData.group : UNGROUPED; + } + }; - // datasets or dataviews - this.nodesData = null; // A DataSet or DataView - this.edgesData = null; // A DataSet or DataView + /** + * Handle updated items + * @param {Number[]} ids + * @protected + */ + ItemSet.prototype._onUpdate = function(ids) { + var me = this; - // 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, params.data); - 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(); - } - }; + ids.forEach(function (id) { + var itemData = me.itemsData.get(id, me.itemOptions); + var item = me.items[id]; + var type = me._getType(itemData); - // 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); + var constructor = ItemSet.types[type]; - // hierarchical layout - this.initializing = false; - if (this.constants.hierarchicalLayout.enabled == true) { - this._setupHierarchicalLayout(); - } - else { - // zoom so all data will fit on the screen, if clustering is enabled, we do not want start to be called here. - if (this.constants.stabilize == false) { - this.zoomExtent({duration:0}, true, this.constants.clustering.enabled); + 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); + } } - } - // if clustering is disabled, the simulation will have started in the setData function - if (this.constants.clustering.enabled) { - this.startWithClustering(); - } - } + 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 + '"'); + } + } + }); - // Extend Network with an Emitter mixin - Emitter(Network.prototype); + this._order(); + this.stackDirty = true; // force re-stacking of all items next redraw + this.body.emitter.emit('change', {queue: true}); + }; /** - * Determine if the browser requires a setTimeout or a requestAnimationFrame. This was required because - * some implementations (safari and IE9) did not support requestAnimationFrame - * @private + * Handle added items + * @param {Number[]} ids + * @protected */ - Network.prototype._determineBrowserMethod = function() { - var browserType = navigator.userAgent.toLowerCase(); - this.requiresTimeout = false; - if (browserType.indexOf('msie 9.0') != -1) { // IE 9 - this.requiresTimeout = true; - } - else if (browserType.indexOf('safari') != -1) { // safari - if (browserType.indexOf('chrome') <= -1) { - this.requiresTimeout = true; - } - } - } - + ItemSet.prototype._onAdd = ItemSet.prototype._onUpdate; /** - * 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 + * Handle removed items + * @param {Number[]} ids + * @protected */ - Network.prototype._getScriptPath = function() { - var scripts = document.getElementsByTagName( 'script' ); - - // find script named vis.js or vis.min.js - for (var i = 0; i < scripts.length; i++) { - var src = scripts[i].src; - var match = src && /\/?vis(.min)?\.js$/.exec(src); - if (match) { - // return path without the script name - return src.substring(0, src.length - match[0].length); + 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); } - } + }); - return null; + if (count) { + // update order + this._order(); + this.stackDirty = true; // force re-stacking of all items next redraw + this.body.emitter.emit('change', {queue: true}); + } }; - /** - * Find the center position of the network + * Update the order of item in all groups * @private */ - Network.prototype._getRange = function(specificNodes) { - var minY = 1e9, maxY = -1e9, minX = 1e9, maxX = -1e9, node; - if (specificNodes.length > 0) { - for (var i = 0; i < specificNodes.length; i++) { - node = this.nodes[specificNodes[i]]; - if (minX > (node.boundingBox.left)) { - minX = node.boundingBox.left; - } - if (maxX < (node.boundingBox.right)) { - maxX = node.boundingBox.right; - } - if (minY > (node.boundingBox.bottom)) { - minY = node.boundingBox.top; - } // top is negative, bottom is positive - if (maxY < (node.boundingBox.top)) { - maxY = node.boundingBox.bottom; - } // top is negative, bottom is positive - } - } - else { - for (var nodeId in this.nodes) { - if (this.nodes.hasOwnProperty(nodeId)) { - node = this.nodes[nodeId]; - if (minX > (node.boundingBox.left)) { - minX = node.boundingBox.left; - } - if (maxX < (node.boundingBox.right)) { - maxX = node.boundingBox.right; - } - if (minY > (node.boundingBox.bottom)) { - minY = node.boundingBox.top; - } // top is negative, bottom is positive - if (maxY < (node.boundingBox.top)) { - maxY = node.boundingBox.bottom; - } // top is negative, bottom is positive - } - } - } - - if (minX == 1e9 && maxX == -1e9 && minY == 1e9 && maxY == -1e9) { - minY = 0, maxY = 0, minX = 0, maxX = 0; - } - return {minX: minX, maxX: maxX, minY: minY, maxY: maxY}; + 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(); + }); }; - /** - * @param {object} range = {minX: minX, maxX: maxX, minY: minY, maxY: maxY}; - * @returns {{x: number, y: number}} + * Handle updated groups + * @param {Number[]} ids * @private */ - Network.prototype._findCenter = function(range) { - return {x: (0.5 * (range.maxX + range.minX)), - y: (0.5 * (range.maxY + range.minY))}; + ItemSet.prototype._onUpdateGroups = function(ids) { + this._onAddGroups(ids); }; - /** - * 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. + * Handle changed groups (added or updated) + * @param {Number[]} ids + * @private */ - Network.prototype.zoomExtent = function(options, initialZoom, disableStart) { - this._redraw(true); + ItemSet.prototype._onAddGroups = function(ids) { + var me = this; - if (initialZoom === undefined) {initialZoom = false;} - if (disableStart === undefined) {disableStart = false;} - if (options === undefined) {options = {nodes:[]};} - if (options.nodes === undefined) { - options.nodes = []; - } + ids.forEach(function (id) { + var groupData = me.groupsData.get(id); + var group = me.groups[id]; - var range; - var zoomLevel; + if (!group) { + // check for reserved ids + if (id == UNGROUPED || id == BACKGROUND) { + throw new Error('Illegal group id. ' + id + ' is a reserved id.'); + } - if (initialZoom == true) { - // check if more than half of the nodes have a predefined position. If so, we use the range, not the approximation. - var positionDefined = 0; - for (var nodeId in this.nodes) { - if (this.nodes.hasOwnProperty(nodeId)) { - var node = this.nodes[nodeId]; - if (node.predefinedPosition == true) { - positionDefined += 1; + var groupOptions = Object.create(me.options); + util.extend(groupOptions, { + height: null + }); + + group = new Group(id, groupData, me); + me.groups[id] = group; + + // add items with this groupId to the new group + for (var itemId in me.items) { + if (me.items.hasOwnProperty(itemId)) { + var item = me.items[itemId]; + if (item.data.group == id) { + group.add(item); + } } } + + group.order(); + group.show(); } - if (positionDefined > 0.5 * this.nodeIndices.length) { - this.zoomExtent(options,false,disableStart); - return; + else { + // update group + group.setData(groupData); } + }); - range = this._getRange(options.nodes); + this.body.emitter.emit('change', {queue: 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. - } + /** + * Handle removed groups + * @param {Number[]} ids + * @private + */ + ItemSet.prototype._onRemoveGroups = function(ids) { + var groups = this.groups; + ids.forEach(function (id) { + var group = groups[id]; + + if (group) { + group.hide(); + delete groups[id]; } + }); - // correct for larger canvasses. - var factor = Math.min(this.frame.canvas.clientWidth / 600, this.frame.canvas.clientHeight / 600); - zoomLevel *= factor; - } - else { - range = this._getRange(options.nodes); - var xDistance = Math.abs(range.maxX - range.minX) * 1.1; - var yDistance = Math.abs(range.maxY - range.minY) * 1.1; + this.markDirty(); - var xZoomLevel = this.frame.canvas.clientWidth / xDistance; - var yZoomLevel = this.frame.canvas.clientHeight / yDistance; - zoomLevel = (xZoomLevel <= yZoomLevel) ? xZoomLevel : yZoomLevel; - } + this.body.emitter.emit('change', {queue: true}); + }; - if (zoomLevel > 1.0) { - zoomLevel = 1.0; - } + /** + * 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(); + }); - var center = this._findCenter(range); - if (disableStart == false) { - var options = {position: center, scale: zoomLevel, animation: options}; - this.moveTo(options); - this.moving = true; - this.start(); + // show the groups again, attach them to the DOM in correct order + groupIds.forEach(function (groupId) { + groups[groupId].show(); + }); + + this.groupIds = groupIds; + } + + return changed; } else { - center.x *= zoomLevel; - center.y *= zoomLevel; - center.x -= 0.5 * this.frame.canvas.clientWidth; - center.y -= 0.5 * this.frame.canvas.clientHeight; - this._setScale(zoomLevel); - this._setTranslation(-center.x,-center.y); + return false; } }; + /** + * Add a new item + * @param {Item} item + * @private + */ + ItemSet.prototype._addItem = function(item) { + this.items[item.id] = item; + + // add to group + var groupId = this._getGroupId(item.data); + var group = this.groups[groupId]; + if (group) group.add(item); + }; /** - * Update the this.nodeIndices with the most recent node index list + * Update an existing item + * @param {Item} item + * @param {Object} itemData * @private */ - Network.prototype._updateNodeIndexList = function() { - this._clearNodeIndexList(); - for (var idx in this.nodes) { - if (this.nodes.hasOwnProperty(idx)) { - this.nodeIndices.push(idx); - } + ItemSet.prototype._updateItem = function(item, itemData) { + var oldGroupId = item.data.group; + + // update the items data (will redraw the item when displayed) + item.setData(itemData); + + // update group + if (oldGroupId != item.data.group) { + var oldGroup = this.groups[oldGroupId]; + if (oldGroup) oldGroup.remove(item); + + var groupId = this._getGroupId(item.data); + var group = this.groups[groupId]; + if (group) group.add(item); } }; - /** - * 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. + * 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 */ - Network.prototype.setData = function(data, disableStart) { - if (disableStart === undefined) { - disableStart = false; - } + ItemSet.prototype._removeItem = function(item) { + // remove from DOM + item.hide(); - // unselect all to ensure no selections from old data are carried over. - this._unselectAll(true); + // remove from items + delete this.items[item.id]; - // we set initializing to true to ensure that the hierarchical layout is not performed until both nodes and edges are added. - this.initializing = true; + // remove from selection + var index = this.selection.indexOf(item.id); + if (index != -1) this.selection.splice(index, 1); - 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.'); - } + // remove from group + item.parent && item.parent.remove(item); + }; - // clean up in case there is anyone in an active mode of the manipulation. This is the same option as bound to the escape button. - if (this.constants.dataManipulation.enabled == true) { - this._createManipulatorBar(); - } + /** + * 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 = []; - // 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; - } - } - else if (data && data.gephi) { - // parse DOT file - if(data && data.gephi) { - var gephiData = gephiParser.parseGephi(data.gephi); - this.setData(gephiData); - return; - } - } - else { - this._setNodes(data && data.nodes); - this._setEdges(data && data.edges); - } - this._putDataInSector(); - if (disableStart == false) { - if (this.constants.hierarchicalLayout.enabled == true) { - this._resetLevels(); - this._setupHierarchicalLayout(); - } - else { - // find a stable position or start animating to a stable position - if (this.constants.stabilize == true) { - this._stabilize(); - } + for (var i = 0; i < array.length; i++) { + if (array[i] instanceof RangeItem) { + endArray.push(array[i]); } - this.start(); } - this.initializing = false; + return endArray; }; /** - * Set options - * @param {Object} options + * 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 */ - Network.prototype.setOptions = function (options) { - if (options) { - var prop; - var fields = ['nodes','edges','smoothCurves','hierarchicalLayout','clustering','navigation', - 'keyboard','dataManipulation','onAdd','onEdit','onEditEdge','onConnect','onDelete','clickToUse' - ]; - // extend all but the values in fields - util.selectiveNotDeepExtend(fields,this.constants, options); - util.selectiveNotDeepExtend(['color'],this.constants.nodes, options.nodes); - util.selectiveNotDeepExtend(['color','length'],this.constants.edges, options.edges); - - this.groups.useDefaultGroups = this.constants.useDefaultGroups; - if (options.physics) { - util.mergeOptions(this.constants.physics, options.physics,'barnesHut'); - util.mergeOptions(this.constants.physics, options.physics,'repulsion'); + ItemSet.prototype._onTouch = function (event) { + // store the touched item, used in _onDragStart + this.touchParams.item = ItemSet.itemFromTarget(event); + }; - 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]; - } - } - } - } + /** + * Start dragging the selected events + * @param {Event} event + * @private + */ + ItemSet.prototype._onDragStart = function (event) { + if (!this.options.editable.updateTime && !this.options.editable.updateGroup) { + return; + } - if (options.onAdd) {this.triggerFunctions.add = options.onAdd;} - if (options.onEdit) {this.triggerFunctions.edit = options.onEdit;} - if (options.onEditEdge) {this.triggerFunctions.editEdge = options.onEditEdge;} - if (options.onConnect) {this.triggerFunctions.connect = options.onConnect;} - if (options.onDelete) {this.triggerFunctions.del = options.onDelete;} + var item = this.touchParams.item || null; + var me = this; + var props; - util.mergeOptions(this.constants, options,'smoothCurves'); - util.mergeOptions(this.constants, options,'hierarchicalLayout'); - util.mergeOptions(this.constants, options,'clustering'); - util.mergeOptions(this.constants, options,'navigation'); - util.mergeOptions(this.constants, options,'keyboard'); - util.mergeOptions(this.constants, options,'dataManipulation'); - - - if (options.dataManipulation) { - this.editMode = this.constants.dataManipulation.initiallyVisible; - } + if (item && item.selected) { + var dragLeftItem = event.target.dragLeftItem; + var dragRightItem = event.target.dragRightItem; + if (dragLeftItem) { + props = { + item: dragLeftItem, + initialX: event.gesture.center.clientX + }; - // TODO: work out these options and document them - if (options.edges) { - if (options.edges.color !== undefined) { - if (util.isString(options.edges.color)) { - this.constants.edges.color = {}; - this.constants.edges.color.color = options.edges.color; - this.constants.edges.color.highlight = options.edges.color; - this.constants.edges.color.hover = options.edges.color; - } - else { - if (options.edges.color.color !== undefined) {this.constants.edges.color.color = options.edges.color.color;} - if (options.edges.color.highlight !== undefined) {this.constants.edges.color.highlight = options.edges.color.highlight;} - if (options.edges.color.hover !== undefined) {this.constants.edges.color.hover = options.edges.color.hover;} - } - this.constants.edges.inheritColor = false; + if (me.options.editable.updateTime) { + props.start = item.data.start.valueOf(); } - - 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;} - } + if (me.options.editable.updateGroup) { + if ('group' in item.data) props.group = item.data.group; } - } - if (options.nodes) { - if (options.nodes.color) { - var newColorObj = util.parseColor(options.nodes.color); - this.constants.nodes.color.background = newColorObj.background; - this.constants.nodes.color.border = newColorObj.border; - this.constants.nodes.color.highlight.background = newColorObj.highlight.background; - this.constants.nodes.color.highlight.border = newColorObj.highlight.border; - this.constants.nodes.color.hover.background = newColorObj.hover.background; - this.constants.nodes.color.hover.border = newColorObj.hover.border; - } - } - if (options.groups) { - for (var groupname in options.groups) { - if (options.groups.hasOwnProperty(groupname)) { - var group = options.groups[groupname]; - this.groups.add(groupname, group); - } - } + this.touchParams.itemProps = [props]; } + else if (dragRightItem) { + props = { + item: dragRightItem, + initialX: event.gesture.center.clientX + }; - if (options.tooltip) { - for (prop in options.tooltip) { - if (options.tooltip.hasOwnProperty(prop)) { - this.constants.tooltip[prop] = options.tooltip[prop]; - } + if (me.options.editable.updateTime) { + props.end = item.data.end.valueOf(); } - if (options.tooltip.color) { - this.constants.tooltip.color = util.parseColor(options.tooltip.color); + if (me.options.editable.updateGroup) { + if ('group' in item.data) props.group = item.data.group; } + + this.touchParams.itemProps = [props]; } + else { + this.touchParams.itemProps = this.getSelection().map(function (id) { + var item = me.items[id]; + var props = { + item: item, + initialX: event.gesture.center.clientX + }; - if ('clickToUse' in options) { - if (options.clickToUse) { - if (!this.activator) { - this.activator = new Activator(this.frame); - this.activator.on('change', this._createKeyBinds.bind(this)); + if (me.options.editable.updateTime) { + if ('start' in item.data) { + props.start = item.data.start.valueOf(); + + if ('end' in item.data) { + // we store a duration here in order not to change the width + // of the item when moving it. + props.duration = item.data.end.valueOf() - props.start; + } + } } - } - else { - if (this.activator) { - this.activator.destroy(); - delete this.activator; + if (me.options.editable.updateGroup) { + if ('group' in item.data) props.group = item.data.group; } - } - } - if (options.labels) { - throw new Error('Option "labels" is deprecated. Use options "locale" and "locales" instead.'); + return props; + }); } - - // (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 hammer - this._bindHammer(); - - // bind keys. If disabled, this will not do anything; - this._createKeyBinds(); - - this._markAllEdgesAsDirty(); - this.setSize(this.constants.width, this.constants.height); - this.moving = true; - if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { - this._resetLevels(); - this._setupHierarchicalLayout(); - } - this.start(); + event.stopPropagation(); } }; - - /** - * 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. + * Drag selected items + * @param {Event} event * @private */ - Network.prototype._create = function () { - // remove all elements from the container element. - while (this.containerElement.hasChildNodes()) { - this.containerElement.removeChild(this.containerElement.firstChild); - } + ItemSet.prototype._onDrag = function (event) { + event.preventDefault(); - this.frame = document.createElement('div'); - this.frame.className = 'vis network-frame'; - this.frame.style.position = 'relative'; - this.frame.style.overflow = 'hidden'; - this.frame.tabIndex = 900; + if (this.touchParams.itemProps) { + var me = this; + var snap = this.options.snap || null; + var xOffset = this.body.dom.root.offsetLeft + this.body.domProps.left.width; + var scale = this.body.util.getScale(); + var step = this.body.util.getStep(); + // move + this.touchParams.itemProps.forEach(function (props) { + var newProps = {}; + var current = me.body.util.toTime(event.gesture.center.clientX - xOffset); + var initial = me.body.util.toTime(props.initialX - xOffset); + var offset = current - initial; - ////////////////////////////////////////////////////////////////// + if ('start' in props) { + var start = new Date(props.start + offset); + newProps.start = snap ? snap(start, scale, step) : start; + } - this.frame.canvas = document.createElement("canvas"); - this.frame.canvas.style.position = 'relative'; - this.frame.appendChild(this.frame.canvas); + if ('end' in props) { + var end = new Date(props.end + offset); + newProps.end = snap ? snap(end, scale, step) : end; + } + else if ('duration' in props) { + newProps.end = new Date(newProps.start.valueOf() + props.duration); + } - 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); - } - else { - var ctx = this.frame.canvas.getContext("2d"); - this.pixelRatio = (window.devicePixelRatio || 1) / (ctx.webkitBackingStorePixelRatio || - ctx.mozBackingStorePixelRatio || - ctx.msBackingStorePixelRatio || - ctx.oBackingStorePixelRatio || - ctx.backingStorePixelRatio || 1); + if ('group' in props) { + // drag from one group to another + var group = me.groupFromTarget(event); + newProps.group = group && group.groupId; + } - //this.pixelRatio = Math.max(1,this.pixelRatio); // this is to account for browser zooming out. The pixel ratio is ment to switch between 1 and 2 for HD screens. - this.frame.canvas.getContext("2d").setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0); - } + // confirm moving the item + var itemData = util.extend({}, props.item.data, newProps); + me.options.onMoving(itemData, function (itemData) { + if (itemData) { + me._updateItemProps(props.item, itemData); + } + }); + }); - this._bindHammer(); - }; + this.stackDirty = true; // force re-stacking of all items next redraw + this.body.emitter.emit('change'); + event.stopPropagation(); + } + }; /** - * This function binds hammer, it can be repeated over and over due to the uniqueness check. + * Update an items properties + * @param {Item} item + * @param {Object} props Can contain properties start, end, and group. * @private */ - Network.prototype._bindHammer = function() { - var me = this; - if (this.hammer !== undefined) { - this.hammer.dispose(); - } - 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('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) ); - - if (this.constants.zoomable == true) { - this.hammer.on('mousewheel', me._onMouseWheel.bind(me)); - this.hammer.on('DOMMouseScroll', me._onMouseWheel.bind(me)); // for FF - this.hammer.on('pinch', me._onPinch.bind(me) ); + ItemSet.prototype._updateItemProps = function(item, props) { + // TODO: copy all properties from props to item? (also new ones) + if ('start' in props) item.data.start = props.start; + if ('end' in props) item.data.end = props.end; + if ('group' in props && item.data.group != props.group) { + this._moveToGroup(item, props.group) } - - this.hammer.on('mousemove', me._onMouseMoveTitle.bind(me) ); - - this.hammerFrame = Hammer(this.frame, { - prevent_default: true - }); - this.hammerFrame.on('release', me._onRelease.bind(me) ); - - // add the frame to the container element - this.containerElement.appendChild(this.frame); - } + }; /** - * Binding the keys for keyboard navigation. These functions are defined in the NavigationMixin + * Move an item to another group + * @param {Item} item + * @param {String | Number} groupId * @private */ - Network.prototype._createKeyBinds = function() { - var me = this; - if (this.keycharm !== undefined) { - this.keycharm.destroy(); - } - - if (this.constants.keyboard.bindToWindow == true) { - this.keycharm = keycharm({container: window, preventDefault: false}); - } - else { - this.keycharm = keycharm({container: this.frame, preventDefault: false}); - } - - this.keycharm.reset(); - - if (this.constants.keyboard.enabled && this.isActive()) { - this.keycharm.bind("up", this._moveUp.bind(me) , "keydown"); - this.keycharm.bind("up", this._yStopMoving.bind(me), "keyup"); - this.keycharm.bind("down", this._moveDown.bind(me) , "keydown"); - this.keycharm.bind("down", this._yStopMoving.bind(me), "keyup"); - this.keycharm.bind("left", this._moveLeft.bind(me) , "keydown"); - this.keycharm.bind("left", this._xStopMoving.bind(me), "keyup"); - this.keycharm.bind("right",this._moveRight.bind(me), "keydown"); - this.keycharm.bind("right",this._xStopMoving.bind(me), "keyup"); - this.keycharm.bind("=", this._zoomIn.bind(me), "keydown"); - this.keycharm.bind("=", this._stopZoom.bind(me), "keyup"); - this.keycharm.bind("num+", this._zoomIn.bind(me), "keydown"); - this.keycharm.bind("num+", this._stopZoom.bind(me), "keyup"); - this.keycharm.bind("num-", this._zoomOut.bind(me), "keydown"); - this.keycharm.bind("num-", this._stopZoom.bind(me), "keyup"); - this.keycharm.bind("-", this._zoomOut.bind(me), "keydown"); - this.keycharm.bind("-", this._stopZoom.bind(me), "keyup"); - this.keycharm.bind("[", this._zoomIn.bind(me), "keydown"); - this.keycharm.bind("[", this._stopZoom.bind(me), "keyup"); - this.keycharm.bind("]", this._zoomOut.bind(me), "keydown"); - this.keycharm.bind("]", this._stopZoom.bind(me), "keyup"); - this.keycharm.bind("pageup",this._zoomIn.bind(me), "keydown"); - this.keycharm.bind("pageup",this._stopZoom.bind(me), "keyup"); - this.keycharm.bind("pagedown",this._zoomOut.bind(me),"keydown"); - this.keycharm.bind("pagedown",this._stopZoom.bind(me), "keyup"); - } + ItemSet.prototype._moveToGroup = function(item, groupId) { + var group = this.groups[groupId]; + if (group && group.groupId != item.data.group) { + var oldGroup = item.parent; + oldGroup.remove(item); + oldGroup.order(); + group.add(item); + group.order(); - if (this.constants.dataManipulation.enabled == true) { - this.keycharm.bind("esc",this._createManipulatorBar.bind(me)); - this.keycharm.bind("delete",this._deleteSelected.bind(me)); + item.data.group = group.groupId; } }; /** - * Cleans up all bindings of the network, removing it fully from the memory IF the variable is set to null after calling this function. - * var network = new vis.Network(..); - * network.destroy(); - * network = null; + * End of dragging selected items + * @param {Event} event + * @private */ - Network.prototype.destroy = function() { - this.start = function () {}; - this.redraw = function () {}; - this.timer = false; + ItemSet.prototype._onDragEnd = function (event) { + event.preventDefault() - // cleanup physicsConfiguration if it exists - this._cleanupPhysicsConfiguration(); + if (this.touchParams.itemProps) { + // prepare a change set for the changed items + var changes = [], + me = this, + dataset = this.itemsData.getDataSet(); - // remove keybindings - this.keycharm.reset(); + var itemProps = this.touchParams.itemProps ; + this.touchParams.itemProps = null; + itemProps.forEach(function (props) { + var id = props.item.id, + itemData = me.itemsData.get(id, me.itemOptions); - // clear hammer bindings - this.hammer.dispose(); + 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; + } - // clear events - this.off(); + // 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 + me._updateItemProps(props.item, props); - this._recursiveDOMDelete(this.containerElement); - } + me.stackDirty = true; // force re-stacking of all items next redraw + me.body.emitter.emit('change'); + } + }); + } + }); - Network.prototype._recursiveDOMDelete = function(DOMobject) { - while (DOMobject.hasChildNodes() == true) { - this._recursiveDOMDelete(DOMobject.firstChild); - DOMobject.removeChild(DOMobject.firstChild); - } - } + // apply the changes to the data (if there are changes) + if (changes.length) { + dataset.update(changes); + } - /** - * 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) - }; + event.stopPropagation(); + } }; /** - * On start of a touch gesture, store the pointer - * @param event + * Handle selecting/deselecting an item when tapping it + * @param {Event} event * @private */ - Network.prototype._onTouch = function (event) { - if (new Date().valueOf() - this.touchTime > 100) { - this.drag.pointer = this._getPointer(event.gesture.center); - this.drag.pinched = false; - this.pinch.scale = this._getScale(); + ItemSet.prototype._onSelectItem = function (event) { + if (!this.options.selectable) return; - // to avoid double fireing of this event because we have two hammer instances. (on canvas and on frame) - this.touchTime = new Date().valueOf(); + 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; + } - this._handleTouch(this.drag.pointer); + var oldSelection = this.getSelection(); + + 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: newSelection + }); } }; /** - * handle drag start event + * Handle creation and updates of an item on double tap + * @param event * @private */ - Network.prototype._onDragStart = function (event) { - this._handleDragStart(event); - }; + ItemSet.prototype._onAddItem = function (event) { + if (!this.options.selectable) return; + if (!this.options.editable.add) return; + var me = this, + snap = this.options.snap || null, + item = ItemSet.itemFromTarget(event); - /** - * 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(event) { - // in case the touch event was triggered on an external div, do the initial touch now. - if (this.drag.pointer === undefined) { - this._onTouch(event); - } + if (item) { + // update item - var node = this._getNodeAt(this.drag.pointer); - // note: drag.pointer is set in _onTouch to get the initial touch location + // 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.getDataSet().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 scale = this.body.util.getScale(); + var step = this.body.util.getStep(); - this.drag.dragging = true; - this.drag.selection = []; - this.drag.translation = this._getTranslation(); - this.drag.nodeId = null; - this.draggingNodes = false; + var newItem = { + start: snap ? snap(start, scale, step) : start, + content: 'new item' + }; - if (node != null && this.constants.dragNodes == true) { - this.draggingNodes = true; - this.drag.nodeId = node.id; - // select the clicked node if not yet selected - if (!node.isSelected()) { - this._selectObject(node,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, scale, step) : end; } - this.emit("dragStart",{nodeIds:this.getSelection().nodes}); + newItem[this.itemsData._fieldId] = util.randomUUID(); - // 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 - }; - - object.xFixed = true; - object.yFixed = true; + var group = this.groupFromTarget(event); + if (group) { + newItem.group = group.groupId; + } - this.drag.selection.push(s); + // execute async handler to customize (or cancel) adding an item + this.options.onAdd(newItem, function (item) { + if (item) { + me.itemsData.getDataSet().add(item); + // TODO: need to trigger a redraw? } - } + }); } }; - /** - * handle drag event + * Handle selecting/deselecting multiple items when holding an item + * @param {Event} event * @private */ - Network.prototype._onDrag = function (event) { - this._handleOnDrag(event) - }; - + ItemSet.prototype._onMultiSelectItem = function (event) { + if (!this.options.selectable) return; - /** - * 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; - } + var selection, + item = ItemSet.itemFromTarget(event); - // remove the focus on node if it is focussed on by the focusOnNode - this.releaseNode(); + if (item) { + // multi select items + selection = this.getSelection(); // current selection - var pointer = this._getPointer(event.gesture.center); - 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; + var shiftKey = event.gesture.touches[0] && event.gesture.touches[0].shiftKey || false; + if (shiftKey) { + // select all items between the old selection and the tapped item - // update position of all selected nodes - selection.forEach(function (s) { - var node = s.node; + // determine the selection range + selection.push(item.id); + var range = ItemSet._getItemRange(this.itemsData.get(selection, this.itemOptions)); - if (!s.xFixed) { - node.x = me._XconvertDOMtoCanvas(me._XconvertCanvasToDOM(s.x) + deltaX); - } + // select all items within the selection range + selection = []; + for (var id in this.items) { + if (this.items.hasOwnProperty(id)) { + var _item = this.items[id]; + var start = _item.data.start; + var end = (_item.data.end !== undefined) ? _item.data.end : start; - if (!s.yFixed) { - node.y = me._YconvertDOMtoCanvas(me._YconvertCanvasToDOM(s.y) + deltaY); + if (start >= range.min && end <= range.max) { + selection.push(_item.id); // do not use id but item.id, id itself is stringified + } + } } - }); - - - // start _animationStep if not yet running - if (!this.moving) { - this.moving = true; - this.start(); } - } - else { - // move the network - if (this.constants.dragNetwork == true) { - // if the drag was not started properly because the click started outside the network div, start it now. - if (this.drag.pointer === undefined) { - this._handleDragStart(event); - return; + else { + // add/remove this item from the current selection + var index = selection.indexOf(item.id); + if (index == -1) { + // item is not yet selected -> select it + selection.push(item.id); + } + else { + // item is already selected -> deselect it + selection.splice(index, 1); } - var diffX = pointer.x - this.drag.pointer.x; - var diffY = pointer.y - this.drag.pointer.y; - - this._setTranslation( - this.drag.translation.x + diffX, - this.drag.translation.y + diffY - ); - this._redraw(); } - } - }; - - /** - * handle drag start event - * @private - */ - Network.prototype._onDragEnd = function (event) { - this._handleDragEnd(event); - }; + this.setSelection(selection); - Network.prototype._handleDragEnd = function(event) { - 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.body.emitter.emit('select', { + items: this.getSelection() }); - this.moving = true; - this.start(); - } - else { - this._redraw(); - } - if (this.draggingNodes == false) { - this.emit("dragEnd",{nodeIds:[]}); - } - else { - this.emit("dragEnd",{nodeIds:this.getSelection().nodes}); } + }; - } /** - * handle tap/click event: select/unselect a node + * Calculate the time range of a list of items + * @param {Array.} itemsData + * @return {{min: Date, max: Date}} Returns the range of the provided items * @private */ - Network.prototype._onTap = function (event) { - var pointer = this._getPointer(event.gesture.center); - this.pointerPosition = pointer; - this._handleTap(pointer); + ItemSet._getItemRange = function(itemsData) { + var max = null; + var min = null; - }; + itemsData.forEach(function (data) { + if (min == null || data.start < min) { + min = data.start; + } + if (data.end != undefined) { + if (max == null || data.end > max) { + max = data.end; + } + } + else { + if (max == null || data.start > max) { + max = data.start; + } + } + }); - /** - * handle doubletap event - * @private - */ - Network.prototype._onDoubleTap = function (event) { - var pointer = this._getPointer(event.gesture.center); - this._handleDoubleTap(pointer); + return { + min: min, + max: max + } }; - /** - * handle long tap event: multi select nodes - * @private + * 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 */ - Network.prototype._onHold = function (event) { - var pointer = this._getPointer(event.gesture.center); - this.pointerPosition = pointer; - this._handleOnHold(pointer); - }; + ItemSet.itemFromTarget = function(event) { + var target = event.target; + while (target) { + if (target.hasOwnProperty('timeline-item')) { + return target['timeline-item']; + } + target = target.parentNode; + } - /** - * handle the release of the screen - * - * @private - */ - Network.prototype._onRelease = function (event) { - var pointer = this._getPointer(event.gesture.center); - this._handleOnRelease(pointer); + return null; }; /** - * Handle pinch event - * @param event - * @private + * 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 */ - Network.prototype._onPinch = function (event) { - var pointer = this._getPointer(event.gesture.center); + ItemSet.prototype.groupFromTarget = function(event) { + // TODO: cleanup when the new solution is stable (also on mobile) + //var target = event.target; + //while (target) { + // if (target.hasOwnProperty('timeline-group')) { + // return target['timeline-group']; + // } + // target = target.parentNode; + //} + // - this.drag.pinched = true; - if (!('scale' in this.pinch)) { - this.pinch.scale = 1; + var clientY = event.gesture.center.clientY; + for (var i = 0; i < this.groupIds.length; i++) { + var groupId = this.groupIds[i]; + var group = this.groups[groupId]; + var foreground = group.dom.foreground; + var top = util.getAbsoluteTop(foreground); + if (clientY > top && clientY < top + foreground.offsetHeight) { + return group; + } + + if (this.options.orientation === 'top') { + if (i === this.groupIds.length - 1 && clientY > top) { + return group; + } + } + else { + if (i === 0 && clientY < top + foreground.offset) { + return group; + } + } } - // TODO: enabled moving while pinching? - var scale = this.pinch.scale * event.gesture.scale; - this._zoom(scale, pointer) + return null; }; /** - * 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 + * 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 */ - 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; + ItemSet.itemSetFromTarget = function(event) { + var target = event.target; + while (target) { + if (target.hasOwnProperty('timeline-itemset')) { + return target['timeline-itemset']; } + target = target.parentNode; + } - 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(); + return null; + }; - var scaleFrac = scale / scaleOld; - var tx = (1 - scaleFrac) * pointer.x + translation.x * scaleFrac; - var ty = (1 - scaleFrac) * pointer.y + translation.y * scaleFrac; + module.exports = ItemSet; - this.areaCenter = {"x" : this._XconvertDOMtoCanvas(pointer.x), - "y" : this._YconvertDOMtoCanvas(pointer.y)}; - this._setScale(scale); - this._setTranslation(tx, ty); - this.updateClustersDefault(); +/***/ }, +/* 27 */ +/***/ function(module, exports, __webpack_require__) { - if (preScaleDragPointer != null) { - var postScaleDragPointer = this.canvasToDOM(preScaleDragPointer); - this.drag.pointer.x = postScaleDragPointer.x; - this.drag.pointer.y = postScaleDragPointer.y; - } + var moment = __webpack_require__(2); + var DateUtil = __webpack_require__(24); + var util = __webpack_require__(1); - this._redraw(); + /** + * @constructor TimeStep + * The class TimeStep is an iterator for dates. You provide a start date and an + * end date. The class itself determines the best scale (step size) based on the + * provided start Date, end Date, and minimumStep. + * + * If minimumStep is provided, the step size is chosen as close as possible + * to the minimumStep but larger than minimumStep. If minimumStep is not + * provided, the scale is set to 1 DAY. + * The minimumStep should correspond with the onscreen size of about 6 characters + * + * Alternatively, you can set a scale by hand. + * After creation, you can initialize the class by executing first(). Then you + * can iterate from the start date to the end date via next(). You can check if + * the end date is reached with the function hasNext(). After each step, you can + * retrieve the current date via getCurrent(). + * The TimeStep has scales ranging from milliseconds, seconds, minutes, hours, + * days, to years. + * + * Version: 1.2 + * + * @param {Date} [start] The start date, for example new Date(2010, 9, 21) + * or new Date(2010, 9, 21, 23, 45, 00) + * @param {Date} [end] The end date + * @param {Number} [minimumStep] Optional. Minimum step size in milliseconds + */ + function TimeStep(start, end, minimumStep, hiddenDates) { + // variables + this.current = new Date(); + this._start = new Date(); + this._end = new Date(); - if (scaleOld < scale) { - this.emit("zoom", {direction:"+"}); - } - else { - this.emit("zoom", {direction:"-"}); - } + this.autoScale = true; + this.scale = 'day'; + this.step = 1; - return scale; + // initialize the range + this.setRange(start, end, minimumStep); + + // hidden Dates options + this.switchedDay = false; + this.switchedMonth = false; + this.switchedYear = false; + this.hiddenDates = hiddenDates; + if (hiddenDates === undefined) { + this.hiddenDates = []; + } + + this.format = TimeStep.FORMAT; // default formatting + } + + // Time formatting + TimeStep.FORMAT = { + minorLabels: { + millisecond:'SSS', + second: 's', + minute: 'HH:mm', + hour: 'HH:mm', + weekday: 'ddd D', + day: 'D', + month: 'MMM', + year: 'YYYY' + }, + majorLabels: { + millisecond:'HH:mm:ss', + second: 'D MMMM HH:mm', + minute: 'ddd D MMMM', + hour: 'ddd D MMMM', + weekday: 'MMMM YYYY', + day: 'MMMM YYYY', + month: 'YYYY', + year: '' } }; + /** + * Set custom formatting for the minor an major labels of the TimeStep. + * Both `minorLabels` and `majorLabels` are an Object with properties: + * 'millisecond, 'second, 'minute', 'hour', 'weekday, 'day, 'month, 'year'. + * @param {{minorLabels: Object, majorLabels: Object}} format + */ + TimeStep.prototype.setFormat = function (format) { + var defaultFormat = util.deepExtend({}, TimeStep.FORMAT); + this.format = util.deepExtend(defaultFormat, format); + }; /** - * 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 + * 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 */ - 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; + TimeStep.prototype.setRange = function(start, end, minimumStep) { + if (!(start instanceof Date) || !(end instanceof Date)) { + throw "No legal start or end date in method setRange"; } - // 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); + this._start = (start != undefined) ? new Date(start.valueOf()) : new Date(); + this._end = (end != undefined) ? new Date(end.valueOf()) : new Date(); - // apply the new scale - this._zoom(scale, pointer); + if (this.autoScale) { + this.setMinimumStep(minimumStep); } - - // Prevent default actions caused by mouse wheel. - event.preventDefault(); }; - /** - * Mouse move handler for checking whether the title moves over a node with a title. - * @param {Event} event - * @private + * Set the range iterator to the start date. */ - Network.prototype._onMouseMoveTitle = function (event) { - var gesture = hammerUtil.fakeGesture(this, event); - var pointer = this._getPointer(gesture.center); - var popupVisible = false; - - // check if the previously selected node is still selected - if (this.popup !== undefined) { - if (this.popup.hidden === false) { - this._checkHidePopup(pointer); - } + TimeStep.prototype.first = function() { + this.current = new Date(this._start.valueOf()); + this.roundToMinor(); + }; - // if the popup was not hidden above - if (this.popup.hidden === false) { - popupVisible = true; - this.popup.setPosition(pointer.x + 3,pointer.y - 5) - this.popup.show(); - } + /** + * Round the current date to the first minor date value + * This must be executed once when the current date is set to start Date + */ + TimeStep.prototype.roundToMinor = function() { + // round to floor + // IMPORTANT: we have no breaks in this switch! (this is no bug) + // noinspection FallThroughInSwitchStatementJS + switch (this.scale) { + case 'year': + this.current.setFullYear(this.step * Math.floor(this.current.getFullYear() / this.step)); + this.current.setMonth(0); + case 'month': this.current.setDate(1); + case 'day': // intentional fall through + case 'weekday': this.current.setHours(0); + case 'hour': this.current.setMinutes(0); + case 'minute': this.current.setSeconds(0); + case 'second': this.current.setMilliseconds(0); + //case 'millisecond': // nothing to do for milliseconds } - // if we bind the keyboard to the div, we have to highlight it to use it. This highlights it on mouse over - if (this.constants.keyboard.bindToWindow == false && this.constants.keyboard.enabled == true) { - this.frame.focus(); + if (this.step != 1) { + // round down to the first minor value that is a multiple of the current step size + switch (this.scale) { + case 'millisecond': this.current.setMilliseconds(this.current.getMilliseconds() - this.current.getMilliseconds() % this.step); break; + case 'second': this.current.setSeconds(this.current.getSeconds() - this.current.getSeconds() % this.step); break; + case 'minute': this.current.setMinutes(this.current.getMinutes() - this.current.getMinutes() % this.step); break; + case 'hour': this.current.setHours(this.current.getHours() - this.current.getHours() % this.step); break; + case 'weekday': // intentional fall through + case 'day': this.current.setDate((this.current.getDate()-1) - (this.current.getDate()-1) % this.step + 1); break; + case 'month': this.current.setMonth(this.current.getMonth() - this.current.getMonth() % this.step); break; + case 'year': this.current.setFullYear(this.current.getFullYear() - this.current.getFullYear() % this.step); break; + default: break; + } } + }; - // start a timeout that will check if the mouse is positioned above an element - if (popupVisible === false) { - 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); - } - } + /** + * 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()); + }; - /** - * 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]; - } - } + /** + * Do the next step + */ + TimeStep.prototype.next = function() { + var prev = this.current.valueOf(); - // adding hover highlights - var obj = this._getNodeAt(pointer); - if (obj == null) { - obj = this._getEdgeAt(pointer); + // 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 'millisecond': + + this.current = new Date(this.current.valueOf() + this.step); break; + case 'second': this.current = new Date(this.current.valueOf() + this.step * 1000); break; + case 'minute': this.current = new Date(this.current.valueOf() + this.step * 1000 * 60); break; + case '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 'weekday': // intentional fall through + case 'day': this.current.setDate(this.current.getDate() + this.step); break; + case 'month': this.current.setMonth(this.current.getMonth() + this.step); break; + case 'year': this.current.setFullYear(this.current.getFullYear() + this.step); break; + default: break; } - if (obj != null) { - this._hoverObject(obj); + } + else { + switch (this.scale) { + case 'millisecond': this.current = new Date(this.current.valueOf() + this.step); break; + case 'second': this.current.setSeconds(this.current.getSeconds() + this.step); break; + case 'minute': this.current.setMinutes(this.current.getMinutes() + this.step); break; + case 'hour': this.current.setHours(this.current.getHours() + this.step); break; + case 'weekday': // intentional fall through + case 'day': this.current.setDate(this.current.getDate() + this.step); break; + case 'month': this.current.setMonth(this.current.getMonth() + this.step); break; + case 'year': this.current.setFullYear(this.current.getFullYear() + this.step); break; + default: break; } + } - // 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.step != 1) { + // round down to the correct major value + switch (this.scale) { + case 'millisecond': if(this.current.getMilliseconds() < this.step) this.current.setMilliseconds(0); break; + case 'second': if(this.current.getSeconds() < this.step) this.current.setSeconds(0); break; + case 'minute': if(this.current.getMinutes() < this.step) this.current.setMinutes(0); break; + case 'hour': if(this.current.getHours() < this.step) this.current.setHours(0); break; + case 'weekday': // intentional fall through + case 'day': if(this.current.getDate() < this.step+1) this.current.setDate(1); break; + case 'month': if(this.current.getMonth() < this.step) this.current.setMonth(0); break; + case 'year': break; // nothing to do for year + default: break; } - this.redraw(); } + + // safety mechanism: if current time is still unchanged, move to the end + if (this.current.valueOf() == prev) { + this.current = new Date(this._end.valueOf()); + } + + DateUtil.stepOverHiddenDates(this, prev); }; + /** - * 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. + * Get the current datetime + * @return {Date} current The current date + */ + TimeStep.prototype.getCurrent = function() { + return this.current; + }; + + /** + * Set a custom scale. Autoscaling will be disabled. + * For example setScale('minute', 5) will result + * in minor steps of 5 minutes, and major steps of an hour. * - * @param {{x:Number, y:Number}} pointer - * @private + * @param {{scale: string, step: number}} params + * An object containing two properties: + * - A string 'scale'. Choose from 'millisecond', 'second', + * 'minute', 'hour', 'weekday, 'day, 'month, 'year'. + * - A number 'step'. A step size, by default 1. + * Choose for example 1, 2, 5, or 10. */ - 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) - }; + TimeStep.prototype.setScale = function(params) { + if (params && typeof params.scale == 'string') { + this.scale = params.scale; + this.step = params.step > 0 ? params.step : 1; + this.autoScale = false; + } + }; - var id; - var previousPopupObjId = this.popupObj === undefined ? "" : this.popupObj.id; - var nodeUnderCursor = false; - var popupType = "node"; + /** + * Enable or disable autoscaling + * @param {boolean} enable If true, autoascaling is set true + */ + TimeStep.prototype.setAutoScale = function (enable) { + this.autoScale = enable; + }; - if (this.popupObj == undefined) { - // search the nodes for overlap, select the top one in case of multiple nodes - var nodes = this.nodes; - var overlappingNodes = []; - for (id in nodes) { - if (nodes.hasOwnProperty(id)) { - var node = nodes[id]; - if (node.isOverlappingWith(obj)) { - if (node.getTitle() !== undefined) { - overlappingNodes.push(id); - } - } - } - } - if (overlappingNodes.length > 0) { - // if there are overlapping nodes, select the last one, this is the - // one which is drawn on top of the others - this.popupObj = this.nodes[overlappingNodes[overlappingNodes.length - 1]]; - // if you hover over a node, the title of the edge is not supposed to be shown. - nodeUnderCursor = true; - } + /** + * Automatically determine the scale that bests fits the provided minimum step + * @param {Number} [minimumStep] The minimum step size in milliseconds + */ + TimeStep.prototype.setMinimumStep = function(minimumStep) { + if (minimumStep == undefined) { + return; } - if (this.popupObj === undefined && nodeUnderCursor == false) { - // search the edges for overlap - var edges = this.edges; - var overlappingEdges = []; - for (id in edges) { - if (edges.hasOwnProperty(id)) { - var edge = edges[id]; - if (edge.connected && (edge.getTitle() !== undefined) && - edge.isOverlappingWith(obj)) { - overlappingEdges.push(id); - } - } - } + //var b = asc + ds; - if (overlappingEdges.length > 0) { - this.popupObj = this.edges[overlappingEdges[overlappingEdges.length - 1]]; - popupType = "edge"; - } - } + 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); - if (this.popupObj) { - // show popup message window - if (this.popupObj.id != previousPopupObjId) { - if (this.popup === undefined) { - this.popup = new Popup(this.frame, this.constants.tooltip); - } + // find the smallest step that is larger than the provided minimumStep + if (stepYear*1000 > minimumStep) {this.scale = 'year'; this.step = 1000;} + if (stepYear*500 > minimumStep) {this.scale = 'year'; this.step = 500;} + if (stepYear*100 > minimumStep) {this.scale = 'year'; this.step = 100;} + if (stepYear*50 > minimumStep) {this.scale = 'year'; this.step = 50;} + if (stepYear*10 > minimumStep) {this.scale = 'year'; this.step = 10;} + if (stepYear*5 > minimumStep) {this.scale = 'year'; this.step = 5;} + if (stepYear > minimumStep) {this.scale = 'year'; this.step = 1;} + if (stepMonth*3 > minimumStep) {this.scale = 'month'; this.step = 3;} + if (stepMonth > minimumStep) {this.scale = 'month'; this.step = 1;} + if (stepDay*5 > minimumStep) {this.scale = 'day'; this.step = 5;} + if (stepDay*2 > minimumStep) {this.scale = 'day'; this.step = 2;} + if (stepDay > minimumStep) {this.scale = 'day'; this.step = 1;} + if (stepDay/2 > minimumStep) {this.scale = 'weekday'; this.step = 1;} + if (stepHour*4 > minimumStep) {this.scale = 'hour'; this.step = 4;} + if (stepHour > minimumStep) {this.scale = 'hour'; this.step = 1;} + if (stepMinute*15 > minimumStep) {this.scale = 'minute'; this.step = 15;} + if (stepMinute*10 > minimumStep) {this.scale = 'minute'; this.step = 10;} + if (stepMinute*5 > minimumStep) {this.scale = 'minute'; this.step = 5;} + if (stepMinute > minimumStep) {this.scale = 'minute'; this.step = 1;} + if (stepSecond*15 > minimumStep) {this.scale = 'second'; this.step = 15;} + if (stepSecond*10 > minimumStep) {this.scale = 'second'; this.step = 10;} + if (stepSecond*5 > minimumStep) {this.scale = 'second'; this.step = 5;} + if (stepSecond > minimumStep) {this.scale = 'second'; this.step = 1;} + if (stepMillisecond*200 > minimumStep) {this.scale = 'millisecond'; this.step = 200;} + if (stepMillisecond*100 > minimumStep) {this.scale = 'millisecond'; this.step = 100;} + if (stepMillisecond*50 > minimumStep) {this.scale = 'millisecond'; this.step = 50;} + if (stepMillisecond*10 > minimumStep) {this.scale = 'millisecond'; this.step = 10;} + if (stepMillisecond*5 > minimumStep) {this.scale = 'millisecond'; this.step = 5;} + if (stepMillisecond > minimumStep) {this.scale = 'millisecond'; this.step = 1;} + }; - this.popup.popupTargetType = popupType; - this.popup.popupTargetId = this.popupObj.id; + /** + * Snap a date to a rounded value. + * The snap intervals are dependent on the current scale and step. + * Static function + * @param {Date} date the date to be snapped. + * @param {string} scale Current scale, can be 'millisecond', 'second', + * 'minute', 'hour', 'weekday, 'day, 'month, 'year'. + * @param {number} step Current step (1, 2, 4, 5, ... + * @return {Date} snappedDate + */ + TimeStep.snap = function(date, scale, step) { + var clone = new Date(date.valueOf()); - // 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 - this.popup.setPosition(pointer.x + 3, pointer.y - 5); - this.popup.setText(this.popupObj.getTitle()); - this.popup.show(); + if (scale == 'year') { + var year = clone.getFullYear() + Math.round(clone.getMonth() / 12); + clone.setFullYear(Math.round(year / step) * step); + clone.setMonth(0); + clone.setDate(0); + clone.setHours(0); + clone.setMinutes(0); + clone.setSeconds(0); + clone.setMilliseconds(0); + } + else if (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); + } + + clone.setHours(0); + clone.setMinutes(0); + clone.setSeconds(0); + clone.setMilliseconds(0); } - else { - if (this.popup) { - this.popup.hide(); + else if (scale == 'day') { + //noinspection FallthroughInSwitchStatementJS + switch (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 (scale == 'weekday') { + //noinspection FallthroughInSwitchStatementJS + switch (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 (scale == 'hour') { + switch (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 (scale == 'minute') { + //noinspection FallthroughInSwitchStatementJS + switch (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 (scale == 'second') { + //noinspection FallthroughInSwitchStatementJS + switch (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 (scale == 'millisecond') { + var _step = step > 5 ? step / 2 : 1; + clone.setMilliseconds(Math.round(clone.getMilliseconds() / _step) * _step); + } + + return clone; }; - /** - * Check if the popup must be hidden, which is the case when the mouse is no - * longer hovering on the object - * @param {{x:Number, y:Number}} pointer - * @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._checkHidePopup = function (pointer) { - var pointerObj = { - left: this._XconvertDOMtoCanvas(pointer.x), - top: this._YconvertDOMtoCanvas(pointer.y), - right: this._XconvertDOMtoCanvas(pointer.x), - bottom: this._YconvertDOMtoCanvas(pointer.y) - }; - - var stillOnObj = false; - if (this.popup.popupTargetType == 'node') { - stillOnObj = this.nodes[this.popup.popupTargetId].isOverlappingWith(pointerObj); - if (stillOnObj === true) { - var overNode = this._getNodeAt(pointer); - stillOnObj = overNode.id == this.popup.popupTargetId; + TimeStep.prototype.isMajor = function() { + if (this.switchedYear == true) { + this.switchedYear = false; + switch (this.scale) { + case 'year': + case 'month': + case 'weekday': + case 'day': + case 'hour': + case 'minute': + case 'second': + case 'millisecond': + return true; + default: + return false; } } - else { - if (this._getNodeAt(pointer) === null) { - stillOnObj = this.edges[this.popup.popupTargetId].isOverlappingWith(pointerObj); + else if (this.switchedMonth == true) { + this.switchedMonth = false; + switch (this.scale) { + case 'weekday': + case 'day': + case 'hour': + case 'minute': + case 'second': + case 'millisecond': + return true; + default: + return false; + } + } + else if (this.switchedDay == true) { + this.switchedDay = false; + switch (this.scale) { + case 'millisecond': + case 'second': + case 'minute': + case 'hour': + return true; + default: + return false; } } - - if (stillOnObj === false) { - this.popupObj = undefined; - this.popup.hide(); + switch (this.scale) { + case 'millisecond': + return (this.current.getMilliseconds() == 0); + case 'second': + return (this.current.getSeconds() == 0); + case 'minute': + return (this.current.getHours() == 0) && (this.current.getMinutes() == 0); + case 'hour': + return (this.current.getHours() == 0); + case 'weekday': // intentional fall through + case 'day': + return (this.current.getDate() == 1); + case 'month': + return (this.current.getMonth() == 0); + case 'year': + return false; + default: + return false; } }; /** - * 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%') + * 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 */ - Network.prototype.setSize = function(width, height) { - var emitEvent = false; - var oldWidth = this.frame.canvas.width; - var oldHeight = this.frame.canvas.height; - if (width != this.constants.width || height != this.constants.height || this.frame.style.width != width || this.frame.style.height != height) { - this.frame.style.width = width; - this.frame.style.height = height; + TimeStep.prototype.getLabelMinor = function(date) { + if (date == undefined) { + date = this.current; + } - this.frame.canvas.style.width = '100%'; - this.frame.canvas.style.height = '100%'; + var format = this.format.minorLabels[this.scale]; + return (format && format.length > 0) ? moment(date).format(format) : ''; + }; - this.frame.canvas.width = this.frame.canvas.clientWidth * this.pixelRatio; - this.frame.canvas.height = this.frame.canvas.clientHeight * this.pixelRatio; + /** + * Returns formatted text for the major axis label, depending on the current + * date and the scale. For example when scale is MINUTE, the major scale is + * hours, and the hour will be formatted as "hh". + * @param {Date} [date] custom date. if not provided, current date is taken + */ + TimeStep.prototype.getLabelMajor = function(date) { + if (date == undefined) { + date = this.current; + } - this.constants.width = width; - this.constants.height = height; + var format = this.format.majorLabels[this.scale]; + return (format && format.length > 0) ? moment(date).format(format) : ''; + }; - emitEvent = true; + TimeStep.prototype.getClassName = function() { + var m = moment(this.current); + var date = m.locale ? m.locale('en') : m.lang('en'); // old versions of moment have .lang() function + var step = this.step; + + function even(value) { + return (value / step % 2 == 0) ? ' even' : ' odd'; } - else { - // this would adapt the width of the canvas to the width from 100% if and only if - // there is a change. - if (this.frame.canvas.width != this.frame.canvas.clientWidth * this.pixelRatio) { - this.frame.canvas.width = this.frame.canvas.clientWidth * this.pixelRatio; - emitEvent = true; + function today(date) { + if (date.isSame(new Date(), 'day')) { + return ' today'; } - if (this.frame.canvas.height != this.frame.canvas.clientHeight * this.pixelRatio) { - this.frame.canvas.height = this.frame.canvas.clientHeight * this.pixelRatio; - emitEvent = true; + if (date.isSame(moment().add(1, 'day'), 'day')) { + return ' tomorrow'; + } + if (date.isSame(moment().add(-1, 'day'), 'day')) { + return ' yesterday'; } + return ''; } - if (emitEvent == true) { - this.emit('resize', {width:this.frame.canvas.width * this.pixelRatio,height:this.frame.canvas.height * this.pixelRatio, oldWidth: oldWidth * this.pixelRatio, oldHeight: oldHeight * this.pixelRatio}); - } - }; - - /** - * 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 (Array.isArray(nodes)) { - this.nodesData = new DataSet(); - this.nodesData.add(nodes); - } - else if (!nodes) { - this.nodesData = new DataSet(); + function currentWeek(date) { + return date.isSame(new Date(), 'week') ? ' current-week' : ''; } - else { - throw new TypeError('Array or DataSet expected'); + + function currentMonth(date) { + return date.isSame(new Date(), 'month') ? ' current-month' : ''; } - if (oldNodesData) { - // unsubscribe from old dataset - util.forEach(this.nodesListeners, function (callback, event) { - oldNodesData.off(event, callback); - }); + function currentYear(date) { + return date.isSame(new Date(), 'year') ? ' current-year' : ''; } - // remove drawn nodes - this.nodes = {}; + switch (this.scale) { + case 'millisecond': + return even(date.milliseconds()).trim(); - if (this.nodesData) { - // subscribe to new dataset - var me = this; - util.forEach(this.nodesListeners, function (callback, event) { - me.nodesData.on(event, callback); - }); + case 'second': + return even(date.seconds()).trim(); - // draw all new nodes - var ids = this.nodesData.getIds(); - this._addNodes(ids); - } - this._updateSelection(); - }; + case 'minute': + return even(date.minutes()).trim(); - /** - * 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 - if ((node.xFixed == false || node.yFixed == false) && (node.x === null || node.y === null)) { - var radius = 10 * 0.1*ids.length + 10; - var angle = 2 * Math.PI * Math.random(); - if (node.xFixed == false) {node.x = radius * Math.cos(angle);} - if (node.yFixed == false) {node.y = radius * Math.sin(angle);} - } - this.moving = true; - } + case 'hour': + var hours = date.hours(); + if (this.step == 4) { + hours = hours + '-' + (hours + 4); + } + return hours + 'h' + today(date) + even(date.hours()); - this._updateNodeIndexList(); - if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { - this._resetLevels(); - this._setupHierarchicalLayout(); + case 'weekday': + return date.format('dddd').toLowerCase() + + today(date) + currentWeek(date) + even(date.date()); + + case 'day': + var day = date.date(); + var month = date.format('MMMM').toLowerCase(); + return 'day' + day + ' ' + month + currentMonth(date) + even(day - 1); + + case 'month': + return date.format('MMMM').toLowerCase() + + currentMonth(date) + even(date.month()); + + case 'year': + var year = date.year(); + return 'year' + year + currentYear(date)+ even(year); + + default: + return ''; } - this._updateCalculationNodes(); - this._reconnectEdges(); - this._updateValueRange(this.nodes); - this.updateLabels(); }; + module.exports = TimeStep; + + +/***/ }, +/* 28 */ +/***/ function(module, exports, __webpack_require__) { + + var util = __webpack_require__(1); + var stack = __webpack_require__(29); + var RangeItem = __webpack_require__(30); + /** - * Update existing nodes, or create them when not yet existing - * @param {Number[] | String[]} ids - * @private + * @constructor Group + * @param {Number | String} groupId + * @param {Object} data + * @param {ItemSet} itemSet */ - Network.prototype._updateNodes = function(ids,changedData) { - var nodes = this.nodes; - for (var i = 0, len = ids.length; i < len; i++) { - var id = ids[i]; - var node = nodes[id]; - var data = changedData[i]; - 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; + function Group (groupId, data, itemSet) { + this.groupId = groupId; + this.subgroups = {}; + this.subgroupIndex = 0; + this.subgroupOrderer = data && data.subgroupOrder; + this.itemSet = itemSet; + + this.dom = {}; + this.props = { + label: { + width: 0, + height: 0 } - } - this.moving = true; - if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { - this._resetLevels(); - this._setupHierarchicalLayout(); - } - this._updateNodeIndexList(); - this._updateValueRange(nodes); - this._markAllEdgesAsDirty(); - }; + }; + this.className = null; + this.items = {}; // items filtered by groupId of this group + this.visibleItems = []; // items currently visible in window + this.orderedItems = { + byStart: [], + byEnd: [] + }; + this.checkRangedItems = false; // needed to refresh the ranged items if the window is programatically changed with NO overlap. + var me = this; + this.itemSet.body.emitter.on("checkRangedItems", function () { + me.checkRangedItems = true; + }) - Network.prototype._markAllEdgesAsDirty = function() { - for (var edgeId in this.edges) { - this.edges[edgeId].colorDirty = true; - } + this._create(); + + this.setData(data); } /** - * Remove existing nodes. If nodes do not exist, the method will just ignore it. - * @param {Number[] | String[]} ids + * Create DOM elements for the group * @private */ - Network.prototype._removeNodes = function(ids) { - var nodes = this.nodes; + Group.prototype._create = function() { + var label = document.createElement('div'); + label.className = 'vlabel'; + this.dom.label = label; - // remove from selection - for (var i = 0, len = ids.length; i < len; i++) { - if (this.selectionObj.nodes[ids[i]] !== undefined) { - this.nodes[ids[i]].unselect(); - this._removeFromSelection(this.nodes[ids[i]]); - } - } + var inner = document.createElement('div'); + inner.className = 'inner'; + label.appendChild(inner); + this.dom.inner = inner; - for (var i = 0, len = ids.length; i < len; i++) { - var id = ids[i]; - delete nodes[id]; - } + 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'; - this._updateNodeIndexList(); - if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { - this._resetLevels(); - this._setupHierarchicalLayout(); - } - this._updateCalculationNodes(); - this._reconnectEdges(); - this._updateSelection(); - this._updateValueRange(nodes); + // 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'; // TODO: ask jos why this is not none? + this.dom.marker.innerHTML = '?'; + this.dom.background.appendChild(this.dom.marker); }; /** - * Load edges by reading the data table - * @param {Array | DataSet | DataView} edges The data containing the edges. - * @private - * @private + * Set the group data for this group + * @param {Object} data Group data, can contain properties content and className */ - Network.prototype._setEdges = function(edges) { - var oldEdgesData = this.edgesData; - - if (edges instanceof DataSet || edges instanceof DataView) { - this.edgesData = edges; - } - else if (Array.isArray(edges)) { - this.edgesData = new DataSet(); - this.edgesData.add(edges); + Group.prototype.setData = function(data) { + // update contents + var content = data && data.content; + if (content instanceof Element) { + this.dom.inner.appendChild(content); } - else if (!edges) { - this.edgesData = new DataSet(); + else if (content !== undefined && content !== null) { + this.dom.inner.innerHTML = content; } else { - throw new TypeError('Array or DataSet expected'); + this.dom.inner.innerHTML = this.groupId || ''; // groupId can be null } - if (oldEdgesData) { - // unsubscribe from old dataset - util.forEach(this.edgesListeners, function (callback, event) { - oldEdgesData.off(event, callback); - }); - } + // update title + this.dom.label.title = data && data.title || ''; - // remove drawn edges - this.edges = {}; + if (!this.dom.inner.firstChild) { + util.addClassName(this.dom.inner, 'hidden'); + } + else { + util.removeClassName(this.dom.inner, 'hidden'); + } - if (this.edgesData) { - // subscribe to new dataset - var me = this; - util.forEach(this.edgesListeners, function (callback, event) { - me.edgesData.on(event, callback); - }); + // update className + var className = data && data.className || null; + if (className != this.className) { + if (this.className) { + util.removeClassName(this.dom.label, this.className); + util.removeClassName(this.dom.foreground, this.className); + util.removeClassName(this.dom.background, this.className); + util.removeClassName(this.dom.axis, this.className); + } + util.addClassName(this.dom.label, className); + util.addClassName(this.dom.foreground, className); + util.addClassName(this.dom.background, className); + util.addClassName(this.dom.axis, className); + this.className = className; + } - // draw all new nodes - var ids = this.edgesData.getIds(); - this._addEdges(ids); + // update style + if (this.style) { + util.removeCssText(this.dom.label, this.style); + this.style = null; } + if (data && data.style) { + util.addCssText(this.dom.label, data.style); + this.style = data.style; + } + }; - this._reconnectEdges(); + /** + * Get the width of the group label + * @return {number} width + */ + Group.prototype.getLabelWidth = function() { + return this.props.label.width; }; + /** - * Add edges - * @param {Number[] | String[]} ids - * @private + * 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 */ - Network.prototype._addEdges = function (ids) { - var edges = this.edges, - edgesData = this.edgesData; + Group.prototype.redraw = function(range, margin, restack) { + var resized = false; - for (var i = 0, len = ids.length; i < len; i++) { - var id = ids[i]; + this.visibleItems = this._updateVisibleItems(this.orderedItems, this.visibleItems, range); - var oldEdge = edges[id]; - if (oldEdge) { - oldEdge.disconnect(); - } + // 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; - var data = edgesData.get(id, {"showInternalIds" : true}); - edges[id] = new Edge(data, this, this.constants); + util.forEach(this.items, function (item) { + item.dirty = true; + if (item.displayed) item.redraw(); + }); + + restack = true; } - this.moving = true; - this._updateValueRange(edges); - this._createBezierNodes(); - this._updateCalculationNodes(); - if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { - this._resetLevels(); - this._setupHierarchicalLayout(); + + // 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, this.subgroups); + } + + // recalculate the height of the group + var height = this._calculateHeight(margin); + + // calculate actual size and position + var foreground = this.dom.foreground; + this.top = foreground.offsetTop; + this.left = foreground.offsetLeft; + this.width = foreground.offsetWidth; + resized = util.updateProperty(this, 'height', height) || resized; + + // recalculate size of label + resized = util.updateProperty(this.props.label, 'width', this.dom.inner.clientWidth) || resized; + resized = util.updateProperty(this.props.label, 'height', this.dom.inner.clientHeight) || resized; + + // apply new height + this.dom.background.style.height = height + 'px'; + this.dom.foreground.style.height = height + 'px'; + this.dom.label.style.height = height + 'px'; + + // update vertical position of items after they are re-stacked and the height of the group is calculated + for (var i = 0, ii = this.visibleItems.length; i < ii; i++) { + var item = this.visibleItems[i]; + item.repositionY(margin); } + + return resized; }; /** - * Update existing edges, or create them when not yet existing - * @param {Number[] | String[]} ids + * recalculate the height of the group + * @param {{item: {horizontal: number, vertical: number}, axis: number}} margin + * @returns {number} Returns the height * @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; + Group.prototype._calculateHeight = function (margin) { + // recalculate the height of the group + var height; + var visibleItems = this.visibleItems; + //var visibleSubgroups = []; + //this.visibleSubgroups = 0; + this.resetSubgroups(); + var me = this; + 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 (item.data.subgroup !== undefined) { + me.subgroups[item.data.subgroup].height = Math.max(me.subgroups[item.data.subgroup].height,item.height); + me.subgroups[item.data.subgroup].visible = true; + //if (visibleSubgroups.indexOf(item.data.subgroup) == -1){ + // visibleSubgroups.push(item.data.subgroup); + // me.visibleSubgroups += 1; + //} + } + }); + 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; } - - this._createBezierNodes(); - if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { - this._resetLevels(); - this._setupHierarchicalLayout(); + else { + height = margin.axis + margin.item.vertical; } - this.moving = true; - this._updateValueRange(edges); + height = Math.max(height, this.props.label.height); + + return height; }; /** - * Remove existing edges. Non existing ids will be ignored - * @param {Number[] | String[]} ids - * @private + * Show this group: attach to the DOM */ - Network.prototype._removeEdges = function (ids) { - var edges = this.edges; + Group.prototype.show = function() { + if (!this.dom.label.parentNode) { + this.itemSet.dom.labelSet.appendChild(this.dom.label); + } - // remove from selection - for (var i = 0, len = ids.length; i < len; i++) { - if (this.selectionObj.edges[ids[i]] !== undefined) { - edges[ids[i]].unselect(); - this._removeFromSelection(edges[ids[i]]); - } + if (!this.dom.foreground.parentNode) { + this.itemSet.dom.foreground.appendChild(this.dom.foreground); } - 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]; - } + if (!this.dom.background.parentNode) { + this.itemSet.dom.background.appendChild(this.dom.background); } - this.moving = true; - this._updateValueRange(edges); - if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { - this._resetLevels(); - this._setupHierarchicalLayout(); + if (!this.dom.axis.parentNode) { + this.itemSet.dom.axis.appendChild(this.dom.axis); } - this._updateCalculationNodes(); }; /** - * Reconnect all edges - * @private + * Hide this group: remove from the DOM */ - Network.prototype._reconnectEdges = function() { - var id, - nodes = this.nodes, - edges = this.edges; - for (id in nodes) { - if (nodes.hasOwnProperty(id)) { - nodes[id].edges = []; - nodes[id].dynamicEdges = []; - } + Group.prototype.hide = function() { + var label = this.dom.label; + if (label.parentNode) { + label.parentNode.removeChild(label); } - for (id in edges) { - if (edges.hasOwnProperty(id)) { - var edge = edges[id]; - edge.from = null; - edge.to = null; - edge.connect(); - } + var foreground = this.dom.foreground; + if (foreground.parentNode) { + foreground.parentNode.removeChild(foreground); } - }; - - /** - * Update the values of all object in the given array according to the current - * value range of the objects in the array. - * @param {Object} obj An object containing a set of Edges or Nodes - * The objects must have a method getValue() and - * setValueRange(min, max). - * @private - */ - Network.prototype._updateValueRange = function(obj) { - var id; - // determine the range of the objects - var valueMin = undefined; - var valueMax = undefined; - var valueTotal = 0; - for (id in obj) { - if (obj.hasOwnProperty(id)) { - var value = obj[id].getValue(); - if (value !== undefined) { - valueMin = (valueMin === undefined) ? value : Math.min(value, valueMin); - valueMax = (valueMax === undefined) ? value : Math.max(value, valueMax); - valueTotal += value; - } - } + var background = this.dom.background; + if (background.parentNode) { + background.parentNode.removeChild(background); } - // adjust the range of all objects - if (valueMin !== undefined && valueMax !== undefined) { - for (id in obj) { - if (obj.hasOwnProperty(id)) { - obj[id].setValueRange(valueMin, valueMax, valueTotal); - } - } + var axis = this.dom.axis; + if (axis.parentNode) { + axis.parentNode.removeChild(axis); } }; /** - * Redraw the network with the current data - * chart will be resized too. + * Add an item to the group + * @param {Item} item */ - Network.prototype.redraw = function() { - this.setSize(this.constants.width, this.constants.height); - this._redraw(); - }; + Group.prototype.add = function(item) { + this.items[item.id] = item; + item.setParent(this); - /** - * Redraw the network with the current data - * @param hidden | used to get the first estimate of the node sizes. only the nodes are drawn after which they are quickly drawn over. - * @private - */ - Network.prototype._requestRedraw = function(hidden) { - if (this.redrawRequested !== true) { - this.redrawRequested = true; - if (this.requiresTimeout === true) { - window.setTimeout(this._redraw.bind(this, hidden),0); - } - else { - window.requestAnimationFrame(this._redraw.bind(this, hidden, true)); + // add to + if (item.data.subgroup !== undefined) { + if (this.subgroups[item.data.subgroup] === undefined) { + this.subgroups[item.data.subgroup] = {height:0, visible: false, index:this.subgroupIndex, items: []}; + this.subgroupIndex++; } + this.subgroups[item.data.subgroup].items.push(item); } - }; + this.orderSubgroups(); - Network.prototype._redraw = function(hidden, requested) { - if (hidden === undefined) { - hidden = false; + 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); } - this.redrawRequested = false; - var ctx = this.frame.canvas.getContext('2d'); - - ctx.setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0); - - // clear the canvas - var w = this.frame.canvas.clientWidth; - var h = this.frame.canvas.clientHeight; - ctx.clearRect(0, 0, w, h); - - // set scaling and translation - ctx.save(); - ctx.translate(this.translation.x, this.translation.y); - ctx.scale(this.scale, this.scale); - - 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) - }; + }; - if (hidden === false) { - this._doInAllSectors("_drawAllSectorNodes", ctx); - if (this.drag.dragging == false || this.drag.dragging === undefined || this.constants.hideEdgesOnDrag == false) { - this._doInAllSectors("_drawEdges", ctx); + Group.prototype.orderSubgroups = function() { + if (this.subgroupOrderer !== undefined) { + var sortArray = []; + if (typeof this.subgroupOrderer == 'string') { + for (var subgroup in this.subgroups) { + sortArray.push({subgroup: subgroup, sortField: this.subgroups[subgroup].items[0].data[this.subgroupOrderer]}) + } + sortArray.sort(function (a, b) { + return a.sortField - b.sortField; + }) + } + else if (typeof this.subgroupOrderer == 'function') { + for (var subgroup in this.subgroups) { + sortArray.push(this.subgroups[subgroup].items[0].data); + } + sortArray.sort(this.subgroupOrderer); } - } - - if (this.drag.dragging == false || this.drag.dragging === undefined || this.constants.hideNodesOnDrag == false) { - this._doInAllSectors("_drawNodes",ctx,false); - } - if (hidden === false) { - if (this.controlNodesActive == true) { - this._doInAllSectors("_drawControlNodes", ctx); + if (sortArray.length > 0) { + for (var i = 0; i < sortArray.length; i++) { + this.subgroups[sortArray[i].subgroup].index = i; + } } } + }; - // this._doInSupportSector("_drawNodes",ctx,true); - // this._drawTree(ctx,"#F00F0F"); - - // restore original scaling and translation - ctx.restore(); - - if (hidden === true) { - ctx.clearRect(0, 0, w, h); + Group.prototype.resetSubgroups = function() { + for (var subgroup in this.subgroups) { + if (this.subgroups.hasOwnProperty(subgroup)) { + this.subgroups[subgroup].visible = false; + } } - } + }; /** - * Set the translation of the network - * @param {Number} offsetX Horizontal offset - * @param {Number} offsetY Vertical offset - * @private + * Remove an item from the group + * @param {Item} item */ - Network.prototype._setTranslation = function(offsetX, offsetY) { - if (this.translation === undefined) { - this.translation = { - x: 0, - y: 0 - }; - } + Group.prototype.remove = function(item) { + delete this.items[item.id]; + item.setParent(null); - if (offsetX !== undefined) { - this.translation.x = offsetX; - } - if (offsetY !== undefined) { - this.translation.y = offsetY; - } + // remove from visible items + var index = this.visibleItems.indexOf(item); + if (index != -1) this.visibleItems.splice(index, 1); - this.emit('viewChanged'); + // TODO: also remove from ordered items? }; - /** - * 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 + * Remove an item from the corresponding DataSet + * @param {Item} item */ - Network.prototype._setScale = function(scale) { - this.scale = scale; + Group.prototype.removeFromDataSet = function(item) { + this.itemSet.removeItem(item.id); }; - /** - * Get the current scale of the network - * @return {Number} scale Scaling factor 1.0 is unscaled - * @private - */ - Network.prototype._getScale = function() { - return this.scale; - }; /** - * 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 + * Reorder the items */ - Network.prototype._XconvertDOMtoCanvas = function(x) { - return (x - this.translation.x) / this.scale; - }; + Group.prototype.order = function() { + var array = util.toArray(this.items); + var startArray = []; + var endArray = []; - /** - * 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; - }; + for (var i = 0; i < array.length; i++) { + if (array[i].data.end !== undefined) { + endArray.push(array[i]); + } + startArray.push(array[i]); + } + this.orderedItems = { + byStart: startArray, + byEnd: endArray + }; - /** - * Convert the Y coordinate in DOM-space (coordinate point in browser relative to the container div) to - * the Y coordinate in canvas-space (the simulation sandbox, which the camera looks upon) - * @param {number} y - * @returns {number} - * @private - */ - Network.prototype._YconvertDOMtoCanvas = function(y) { - return (y - this.translation.y) / this.scale; + stack.orderByStart(this.orderedItems.byStart); + stack.orderByEnd(this.orderedItems.byEnd); }; + /** - * 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} + * 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 */ - Network.prototype._YconvertCanvasToDOM = function(y) { - return y * this.scale + this.translation.y ; - }; + Group.prototype._updateVisibleItems = function(orderedItems, oldVisibleItems, range) { + var visibleItems = []; + var visibleItemsLookup = {}; // we keep this to quickly look up if an item already exists in the list without using indexOf on visibleItems + var interval = (range.end - range.start) / 4; + var lowerBound = range.start - interval; + var upperBound = range.end + interval; + var item, i; + // this function is used to do the binary search. + var searchFunction = function (value) { + if (value < lowerBound) {return -1;} + else if (value <= upperBound) {return 0;} + else {return 1;} + } - /** - * - * @param {object} pos = {x: number, y: number} - * @returns {{x: number, y: number}} - * @constructor - */ - Network.prototype.canvasToDOM = function (pos) { - return {x: this._XconvertCanvasToDOM(pos.x), y: this._YconvertCanvasToDOM(pos.y)}; - }; + // first check if the items that were in view previously are still in view. + // IMPORTANT: this handles the case for the items with startdate before the window and enddate after the window! + // also cleans up invisible items. + if (oldVisibleItems.length > 0) { + for (i = 0; i < oldVisibleItems.length; i++) { + this._checkIfVisibleWithReference(oldVisibleItems[i], visibleItems, visibleItemsLookup, range); + } + } - /** - * - * @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)}; - }; + // we do a binary search for the items that have only start values. + var initialPosByStart = util.binarySearchCustom(orderedItems.byStart, searchFunction, 'data','start'); - /** - * Redraw all nodes - * The 2d context of a HTML canvas can be retrieved by canvas.getContext('2d'); - * @param {CanvasRenderingContext2D} ctx - * @param {Boolean} [alwaysShow] - * @private - */ - Network.prototype._drawNodes = function(ctx,alwaysShow) { - if (alwaysShow === undefined) { - alwaysShow = false; + // trace the visible items from the inital start pos both ways until an invisible item is found, we only look at the start values. + this._traceVisible(initialPosByStart, orderedItems.byStart, visibleItems, visibleItemsLookup, function (item) { + return (item.data.start < lowerBound || item.data.start > upperBound); + }); + + // if the window has changed programmatically without overlapping the old window, the ranged items with start < lowerBound and end > upperbound are not shown. + // We therefore have to brute force check all items in the byEnd list + if (this.checkRangedItems == true) { + this.checkRangedItems = false; + for (i = 0; i < orderedItems.byEnd.length; i++) { + this._checkIfVisibleWithReference(orderedItems.byEnd[i], visibleItems, visibleItemsLookup, range); + } } + else { + // we do a binary search for the items that have defined end times. + var initialPosByEnd = util.binarySearchCustom(orderedItems.byEnd, searchFunction, 'data','end'); - // first draw the unselected nodes - var nodes = this.nodes; - var selected = []; + // trace the visible items from the inital start pos both ways until an invisible item is found, we only look at the end values. + this._traceVisible(initialPosByEnd, orderedItems.byEnd, visibleItems, visibleItemsLookup, function (item) { + return (item.data.end < lowerBound || item.data.end > upperBound); + }); + } - 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); + + // finally, we reposition all the visible items. + for (i = 0; i < visibleItems.length; i++) { + item = visibleItems[i]; + if (!item.displayed) item.show(); + // reposition item horizontally + item.repositionX(); + } + + // debug + //console.log("new line") + //if (this.groupId == null) { + // for (i = 0; i < orderedItems.byStart.length; i++) { + // item = orderedItems.byStart[i].data; + // console.log('start',i,initialPosByStart, item.start.valueOf(), item.content, item.start >= lowerBound && item.start <= upperBound,i == initialPosByStart ? "<------------------- HEREEEE" : "") + // } + // for (i = 0; i < orderedItems.byEnd.length; i++) { + // item = orderedItems.byEnd[i].data; + // console.log('rangeEnd',i,initialPosByEnd, item.end.valueOf(), item.content, item.end >= range.start && item.end <= range.end,i == initialPosByEnd ? "<------------------- HEREEEE" : "") + // } + //} + + return visibleItems; + }; + + Group.prototype._traceVisible = function (initialPos, items, visibleItems, visibleItemsLookup, breakCondition) { + var item; + var i; + + if (initialPos != -1) { + for (i = initialPos; i >= 0; i--) { + item = items[i]; + if (breakCondition(item)) { + break; } else { - if (nodes[id].inArea() || alwaysShow) { - nodes[id].draw(ctx); + if (visibleItemsLookup[item.id] === undefined) { + visibleItemsLookup[item.id] = true; + visibleItems.push(item); } } } - } - // 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); + for (i = initialPos + 1; i < items.length; i++) { + item = items[i]; + if (breakCondition(item)) { + break; + } + else { + if (visibleItemsLookup[item.id] === undefined) { + visibleItemsLookup[item.id] = true; + visibleItems.push(item); + } + } } } - }; + } + /** - * Redraw all edges - * The 2d context of a HTML canvas can be retrieved by canvas.getContext('2d'); - * @param {CanvasRenderingContext2D} ctx + * 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 */ - 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); - } + 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(); } - } }; + /** - * Redraw all edges - * The 2d context of a HTML canvas can be retrieved by canvas.getContext('2d'); - * @param {CanvasRenderingContext2D} ctx + * 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 */ - Network.prototype._drawControlNodes = function(ctx) { - var edges = this.edges; - for (var id in edges) { - if (edges.hasOwnProperty(id)) { - edges[id]._drawControlNodes(ctx); + Group.prototype._checkIfVisibleWithReference = function(item, visibleItems, visibleItemsLookup, range) { + if (item.isVisible(range)) { + if (visibleItemsLookup[item.id] === undefined) { + visibleItemsLookup[item.id] = true; + visibleItems.push(item); } } + else { + if (item.displayed) item.hide(); + } }; - /** - * Find a stable position for all nodes - * @private - */ - Network.prototype._stabilize = function() { - if (this.constants.freezeForStabilization == true) { - this._freezeDefinedNodes(); - } - // find stable position - var count = 0; - while (this.moving && count < this.constants.stabilizationIterations) { - this._physicsTick(); - count++; - } + module.exports = Group; - if (this.constants.zoomExtentOnStabilize == true) { - this.zoomExtent({duration:0}, false, true); - } - if (this.constants.freezeForStabilization == true) { - this._restoreFrozenNodes(); - } +/***/ }, +/* 29 */ +/***/ function(module, exports, __webpack_require__) { - this.emit("stabilizationIterationsDone"); - }; + // Utility functions for ordering and stacking of items + var EPSILON = 0.001; // used when checking collisions, to prevent round-off errors /** - * 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 + * Order items by their start data + * @param {Item[]} items */ - 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; - } - } - } + exports.orderByStart = function(items) { + items.sort(function (a, b) { + return a.data.start - b.data.start; + }); }; /** - * Unfreezes the nodes that have been frozen by _freezeDefinedNodes. - * - * @private + * Order items by their end date. If they have no end date, their start date + * is used. + * @param {Item[]} items */ - 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; - } - } - } - }; - + 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; - /** - * 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[id] !== undefined) { - if (nodes[id].isMoving(vmin) == true) { - return true; - } - } - } - return false; + return aTime - bTime; + }); }; - /** - * /** - * Perform one discrete step for all nodes - * - * @private + * 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 */ - Network.prototype._discreteStepNodes = function() { - var interval = this.physicsDiscreteStepsize; - var nodes = this.nodes; - var nodeId; - var nodesPresent = false; + exports.stack = function(items, margin, force) { + var i, iMax; - 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; - } + if (force) { + // reset top position of all items + for (i = 0, iMax = items.length; i < iMax; i++) { + items[i].top = null; } } - if (nodesPresent == true) { - var vminCorrected = this.constants.minVelocity / Math.max(this.scale,0.05); - if (vminCorrected > 0.5*this.constants.maxVelocity) { - return true; - } - else { - return this._isMoving(vminCorrected); - } - } - return false; - }; + // calculate new, non-overlapping positions + for (i = 0, iMax = items.length; i < iMax; i++) { + var item = items[i]; + if (item.stack && item.top === null) { + // initialize top position + item.top = margin.axis; + do { + // TODO: optimize checking for overlap. when there is a gap without items, + // you only need to check for items from the next item on, not from zero + var collidingItem = null; + for (var j = 0, jj = items.length; j < jj; j++) { + var other = items[j]; + if (other.top !== null && other !== item && other.stack && exports.collision(item, other, margin.item)) { + collidingItem = other; + break; + } + } - Network.prototype._revertPhysicsState = function() { - var nodes = this.nodes; - for (var nodeId in nodes) { - if (nodes.hasOwnProperty(nodeId)) { - nodes[nodeId].revertPosition(); + 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); } } - } + }; - Network.prototype._revertPhysicsTick = function() { - this._doInAllActiveSectors("_revertPhysicsState"); - if (this.constants.smoothCurves.enabled == true && this.constants.smoothCurves.dynamic == true) { - this._doInSupportSector("_revertPhysicsState"); - } - } /** - * A single simulation step (or "tick") in the physics simulation - * - * @private + * 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. */ - Network.prototype._physicsTick = function() { - if (!this.freezeSimulationEnabled) { - if (this.moving == true) { - var mainMovingStatus = false; - var supportMovingStatus = false; - - this._doInAllActiveSectors("_initializeForceCalculation"); - var mainMoving = this._doInAllActiveSectors("_discreteStepNodes"); - if (this.constants.smoothCurves.enabled == true && this.constants.smoothCurves.dynamic == true) { - supportMovingStatus = this._doInSupportSector("_discreteStepNodes"); - } - - // gather movement data from all sectors, if one moves, we are NOT stabilzied - for (var i = 0; i < mainMoving.length; i++) { - mainMovingStatus = mainMoving[i] || mainMovingStatus; - } + exports.nostack = function(items, margin, subgroups) { + var i, iMax, newTop; - // determine if the network has stabilzied - this.moving = mainMovingStatus || supportMovingStatus; - if (this.moving == false) { - this._revertPhysicsTick(); - } - else { - // this is here to ensure that there is no start event when the network is already stable. - if (this.startedStabilization == false) { - this.emit("startStabilization"); - this.startedStabilization = true; + // reset top position of all items + for (i = 0, iMax = items.length; i < iMax; i++) { + if (items[i].data.subgroup !== undefined) { + newTop = margin.axis; + for (var subgroup in subgroups) { + if (subgroups.hasOwnProperty(subgroup)) { + if (subgroups[subgroup].visible == true && subgroups[subgroup].index < subgroups[items[i].data.subgroup].index) { + newTop += subgroups[subgroup].height + margin.item.vertical; + } } } - - this.stabilizationIterations++; + items[i].top = newTop; + } + else { + items[i].top = margin.axis; } } }; - /** - * 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 + * 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 */ - Network.prototype._animationStep = function() { - // reset the timer so a new scheduled animation step can be set - this.timer = undefined; + 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); + }; - if (this.requiresTimeout == true) { - // this schedules a new animation step - this.start(); - } - // handle the keyboad movement - this._handleNavigation(); +/***/ }, +/* 30 */ +/***/ function(module, exports, __webpack_require__) { - // check if the physics have settled - if (this.moving == true) { - var startTime = Date.now(); - this._physicsTick(); - var physicsTime = Date.now() - startTime; + var Hammer = __webpack_require__(19); + var Item = __webpack_require__(31); - // run double speed if it is a little graph - if ((this.renderTimestep - this.renderTime > 2 * physicsTime || this.runDoubleSpeed == true) && this.moving == true) { - this._physicsTick(); + /** + * @constructor RangeItem + * @extends Item + * @param {Object} data Object containing parameters start, end + * content, className. + * @param {{toScreen: function, toTime: function}} conversion + * Conversion functions from time to screen and vice versa + * @param {Object} [options] Configuration options + * // TODO: describe options + */ + function RangeItem (data, conversion, options) { + this.props = { + content: { + width: 0 + } + }; + this.overflow = false; // if contents can overflow (css styling), this flag is set to true - // this makes sure there is no jitter. The decision is taken once to run it at double speed. - if (this.renderTime != 0) { - this.runDoubleSpeed = true - } + // validate data + if (data) { + if (data.start == undefined) { + throw new Error('Property "start" missing in item ' + data.id); + } + if (data.end == undefined) { + throw new Error('Property "end" missing in item ' + data.id); } } - var renderStartTime = Date.now(); - this._redraw(); - this.renderTime = Date.now() - renderStartTime; + Item.call(this, data, conversion, options); + } - if (this.requiresTimeout == false) { - // this schedules a new animation step - this.start(); - } - }; + RangeItem.prototype = new Item (null, null, null); - if (typeof window !== 'undefined') { - window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || - window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; - } + RangeItem.prototype.baseClassName = 'item range'; /** - * Schedule a animation step with the refreshrate interval. + * 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 */ - Network.prototype.start = function() { - if (this.freezeSimulationEnabled == true) { - this.moving = false; - } - if (this.moving == true || this.xIncrement != 0 || this.yIncrement != 0 || this.zoomIncrement != 0 || this.animating == true) { - if (!this.timer) { - if (this.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)); // wait this.renderTimeStep milliseconds and perform the animation step function - } - } - } - else { - this._requestRedraw(); - // this check is to ensure that the network does not emit these events if it was already stabilized and setOptions is called (setting moving to true and calling start()) - if (this.stabilizationIterations > 1) { - // trigger the "stabilized" event. - // The event is triggered on the next tick, to prevent the case that - // it is fired while initializing the Network, in which case you would not - // be able to catch it - var me = this; - var params = { - iterations: me.stabilizationIterations - }; - this.stabilizationIterations = 0; - this.startedStabilization = false; - setTimeout(function () { - me.emit("stabilized", params); - }, 0); - } - else { - this.stabilizationIterations = 0; - } - } + RangeItem.prototype.isVisible = function(range) { + // determine visibility + return (this.data.start < range.end) && (this.data.end > range.start); }; - /** - * Move the network according to the keyboard presses. - * - * @private + * Repaint the item */ - Network.prototype._handleNavigation = function() { - if (this.xIncrement != 0 || this.yIncrement != 0) { - var translation = this._getTranslation(); - this._setTranslation(translation.x+this.xIncrement, translation.y+this.yIncrement); - } - if (this.zoomIncrement != 0) { - var center = { - x: this.frame.canvas.clientWidth / 2, - y: this.frame.canvas.clientHeight / 2 - }; - this._zoom(this.scale*(1 + this.zoomIncrement), center); - } - }; + RangeItem.prototype.redraw = function() { + var dom = this.dom; + if (!dom) { + // create DOM + this.dom = {}; + dom = this.dom; + // background box + dom.box = document.createElement('div'); + // className is updated in redraw() - /** - * Freeze the _animationStep - */ - Network.prototype.freezeSimulation = function(freeze) { - if (freeze == true) { - this.freezeSimulationEnabled = true; - this.moving = false; - } - else { - this.freezeSimulationEnabled = false; - this.moving = true; - this.start(); - } - }; + // 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; - /** - * This function cleans the support nodes if they are not needed and adds them when they are. - * - * @param {boolean} [disableStart] - * @private - */ - Network.prototype._configureSmoothCurves = function(disableStart) { - if (disableStart === undefined) { - disableStart = true; + this.dirty = true; } - if (this.constants.smoothCurves.enabled == true && this.constants.smoothCurves.dynamic == true) { - this._createBezierNodes(); - // cleanup unused support nodes - for (var nodeId in this.sectors['support']['nodes']) { - if (this.sectors['support']['nodes'].hasOwnProperty(nodeId)) { - if (this.edges[this.sectors['support']['nodes'][nodeId].parentEdgeId] === undefined) { - delete this.sectors['support']['nodes'][nodeId]; - } - } - } + + // append DOM to parent DOM + if (!this.parent) { + throw new Error('Cannot redraw item: no parent attached'); } - else { - // delete the support nodes - this.sectors['support']['nodes'] = {}; - for (var edgeId in this.edges) { - if (this.edges.hasOwnProperty(edgeId)) { - this.edges[edgeId].via = null; - } + if (!dom.box.parentNode) { + var foreground = this.parent.dom.foreground; + if (!foreground) { + throw new Error('Cannot redraw item: parent has no foreground container element'); } + foreground.appendChild(dom.box); } + this.displayed = true; + + // Update DOM when item is marked dirty. An item is marked dirty when: + // - the item is not yet rendered + // - the item's data is changed + // - the item is selected/deselected + if (this.dirty) { + this._updateContents(this.dom.content); + this._updateTitle(this.dom.box); + this._updateDataAttributes(this.dom.box); + this._updateStyle(this.dom.box); + // update class + var className = (this.data.className ? (' ' + this.data.className) : '') + + (this.selected ? ' selected' : ''); + dom.box.className = this.baseClassName + className; - this._updateCalculationNodes(); - if (!disableStart) { - this.moving = true; - this.start(); - } - }; + // determine from css whether this box has overflow + this.overflow = window.getComputedStyle(dom.content).overflow !== 'hidden'; + // recalculate size + // turn off max-width to be able to calculate the real width + // this causes an extra browser repaint/reflow, but so be it + this.dom.content.style.maxWidth = 'none'; + this.props.content.width = this.dom.content.offsetWidth; + this.height = this.dom.box.offsetHeight; + this.dom.content.style.maxWidth = ''; - /** - * Bezier curves require an anchor point to calculate the smooth flow. These points are nodes. These nodes are invisible but - * are used for the force calculation. - * - * @private - */ - Network.prototype._createBezierNodes = function() { - if (this.constants.smoothCurves.enabled == true && this.constants.smoothCurves.dynamic == true) { - for (var edgeId in this.edges) { - if (this.edges.hasOwnProperty(edgeId)) { - var edge = this.edges[edgeId]; - if (edge.via == null) { - var nodeId = "edgeId:".concat(edge.id); - this.sectors['support']['nodes'][nodeId] = new Node( - {id:nodeId, - mass:1, - shape:'circle', - image:"", - internalMultiplier:1 - },{},{},this.constants); - edge.via = this.sectors['support']['nodes'][nodeId]; - edge.via.parentEdgeId = edge.id; - edge.positionBezierNode(); - } - } - } + this.dirty = false; } + + this._repaintDeleteButton(dom.box); + this._repaintDragLeft(); + this._repaintDragRight(); }; /** - * load the functions that load the mixins into the prototype. - * - * @private + * Show the item in the DOM (when not already visible). The items DOM will + * be created when needed. */ - Network.prototype._initializeMixinLoaders = function () { - for (var mixin in MixinLoader) { - if (MixinLoader.hasOwnProperty(mixin)) { - Network.prototype[mixin] = MixinLoader[mixin]; - } + RangeItem.prototype.show = function() { + if (!this.displayed) { + this.redraw(); } }; /** - * Load the XY positions of the nodes into the dataset. + * Hide the item from the DOM (when visible) + * @return {Boolean} changed */ - Network.prototype.storePosition = function() { - console.log("storePosition is depricated: use .storePositions() from now on.") - this.storePositions(); - }; + RangeItem.prototype.hide = function() { + if (this.displayed) { + var box = this.dom.box; - /** - * Load the XY positions of the nodes into the dataset. - */ - Network.prototype.storePositions = 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}); - } + if (box.parentNode) { + box.parentNode.removeChild(box); } + + this.top = null; + this.left = null; + + this.displayed = false; } - this.nodesData.update(dataArray); }; /** - * Return the positions of the nodes. + * Reposition the item horizontally + * @Override */ - Network.prototype.getPositions = function(ids) { - var dataArray = {}; - if (ids !== undefined) { - if (Array.isArray(ids) == true) { - for (var i = 0; i < ids.length; i++) { - if (this.nodes[ids[i]] !== undefined) { - var node = this.nodes[ids[i]]; - dataArray[ids[i]] = {x: Math.round(node.x), y: Math.round(node.y)}; - } - } - } - else { - if (this.nodes[ids] !== undefined) { - var node = this.nodes[ids]; - dataArray[ids] = {x: Math.round(node.x), y: Math.round(node.y)}; - } - } + RangeItem.prototype.repositionX = function() { + var parentWidth = this.parent.width; + var start = this.conversion.toScreen(this.data.start); + var end = this.conversion.toScreen(this.data.end); + var contentLeft; + var contentWidth; + + // limit the width of the this, as browsers cannot draw very wide divs + if (start < -parentWidth) { + start = -parentWidth; } - else { - for (var nodeId in this.nodes) { - if (this.nodes.hasOwnProperty(nodeId)) { - var node = this.nodes[nodeId]; - dataArray[nodeId] = {x: Math.round(node.x), y: Math.round(node.y)}; - } - } + if (end > 2 * parentWidth) { + end = 2 * parentWidth; } - return dataArray; - }; + var boxWidth = Math.max(end - start, 1); + + if (this.overflow) { + this.left = start; + this.width = boxWidth + this.props.content.width; + contentWidth = this.props.content.width; + + // Note: The calculation of width is an optimistic calculation, giving + // a width which will not change when moving the Timeline + // So no re-stacking needed, which is nicer for the eye; + } + else { + this.left = start; + this.width = boxWidth; + contentWidth = Math.min(end - start - 2 * this.options.padding, this.props.content.width); + } + + this.dom.box.style.left = this.left + 'px'; + this.dom.box.style.width = boxWidth + 'px'; + + switch (this.options.align) { + case 'left': + this.dom.content.style.left = '0'; + break; + + case 'right': + this.dom.content.style.left = Math.max((boxWidth - contentWidth - 2 * this.options.padding), 0) + 'px'; + break; + case 'center': + this.dom.content.style.left = Math.max((boxWidth - contentWidth - 2 * this.options.padding) / 2, 0) + 'px'; + break; + default: // 'auto' + // when range exceeds left of the window, position the contents at the left of the visible area + if (this.overflow) { + if (end > 0) { + contentLeft = Math.max(-start, 0); + } + else { + contentLeft = -contentWidth; // ensure it's not visible anymore + } + } + else { + if (start < 0) { + contentLeft = Math.min(-start, + (end - start - contentWidth - 2 * this.options.padding)); + // TODO: remove the need for options.padding. it's terrible. + } + else { + contentLeft = 0; + } + } + this.dom.content.style.left = contentLeft + 'px'; + } + }; /** - * Center a node in view. - * - * @param {Number} nodeId - * @param {Number} [options] + * Reposition the item vertically + * @Override */ - Network.prototype.focusOnNode = function (nodeId, options) { - if (this.nodes.hasOwnProperty(nodeId)) { - if (options === undefined) { - options = {}; - } - var nodePosition = {x: this.nodes[nodeId].x, y: this.nodes[nodeId].y}; - options.position = nodePosition; - options.lockedOnNode = nodeId; + RangeItem.prototype.repositionY = function() { + var orientation = this.options.orientation, + box = this.dom.box; - this.moveTo(options) + if (orientation == 'top') { + box.style.top = this.top + 'px'; } else { - console.log("This nodeId cannot be found."); + box.style.top = (this.parent.height - this.top - this.height) + 'px'; } }; /** - * - * @param {Object} options | options.offset = {x:Number, y:Number} // offset from the center in DOM pixels - * | options.scale = Number // scale to move to - * | options.position = {x:Number, y:Number} // position to move to - * | options.animation = {duration:Number, easingFunction:String} || Boolean // position to move to + * Repaint a drag area on the left side of the range when the range is selected + * @protected */ - Network.prototype.moveTo = function (options) { - if (options === undefined) { - options = {}; - return; - } - if (options.offset === undefined) {options.offset = {x: 0, y: 0}; } - if (options.offset.x === undefined) {options.offset.x = 0; } - if (options.offset.y === undefined) {options.offset.y = 0; } - if (options.scale === undefined) {options.scale = this._getScale(); } - if (options.position === undefined) {options.position = this._getTranslation();} - if (options.animation === undefined) {options.animation = {duration:0}; } - if (options.animation === false ) {options.animation = {duration:0}; } - if (options.animation === true ) {options.animation = {}; } - if (options.animation.duration === undefined) {options.animation.duration = 1000; } // default duration - if (options.animation.easingFunction === undefined) {options.animation.easingFunction = "easeInOutQuad"; } // default easing function + RangeItem.prototype._repaintDragLeft = function () { + if (this.selected && this.options.editable.updateTime && !this.dom.dragLeft) { + // create and show drag area + var dragLeft = document.createElement('div'); + dragLeft.className = 'drag-left'; + dragLeft.dragLeftItem = this; - this.animateView(options); + // TODO: this should be redundant? + Hammer(dragLeft, { + preventDefault: true + }).on('drag', function () { + //console.log('drag left') + }); + + this.dom.box.appendChild(dragLeft); + this.dom.dragLeft = dragLeft; + } + else if (!this.selected && this.dom.dragLeft) { + // delete drag area + if (this.dom.dragLeft.parentNode) { + this.dom.dragLeft.parentNode.removeChild(this.dom.dragLeft); + } + this.dom.dragLeft = null; + } }; /** - * - * @param {Object} options | options.offset = {x:Number, y:Number} // offset from the center in DOM pixels - * | options.time = Number // animation time in milliseconds - * | options.scale = Number // scale to animate to - * | options.position = {x:Number, y:Number} // position to animate to - * | options.easingFunction = String // linear, easeInQuad, easeOutQuad, easeInOutQuad, - * // easeInCubic, easeOutCubic, easeInOutCubic, - * // easeInQuart, easeOutQuart, easeInOutQuart, - * // easeInQuint, easeOutQuint, easeInOutQuint + * Repaint a drag area on the right side of the range when the range is selected + * @protected */ - Network.prototype.animateView = function (options) { - if (options === undefined) { - options = {}; - return; - } + RangeItem.prototype._repaintDragRight = function () { + if (this.selected && this.options.editable.updateTime && !this.dom.dragRight) { + // create and show drag area + var dragRight = document.createElement('div'); + dragRight.className = 'drag-right'; + dragRight.dragRightItem = this; - // release if something focussed on the node - this.releaseNode(); - if (options.locked == true) { - this.lockedOnNodeId = options.lockedOnNode; - this.lockedOnNodeOffset = options.offset; - } + // TODO: this should be redundant? + Hammer(dragRight, { + preventDefault: true + }).on('drag', function () { + //console.log('drag right') + }); - // forcefully complete the old animation if it was still running - if (this.easingTime != 0) { - this._transitionRedraw(1); // by setting easingtime to 1, we finish the animation. + this.dom.box.appendChild(dragRight); + this.dom.dragRight = dragRight; } - - this.sourceScale = this._getScale(); - this.sourceTranslation = this._getTranslation(); - this.targetScale = options.scale; - - // set the scale so the viewCenter is based on the correct zoom level. This is overridden in the transitionRedraw - // but at least then we'll have the target transition - this._setScale(this.targetScale); - var viewCenter = this.DOMtoCanvas({x: 0.5 * this.frame.canvas.clientWidth, y: 0.5 * this.frame.canvas.clientHeight}); - var distanceFromCenter = { // offset from view, distance view has to change by these x and y to center the node - x: viewCenter.x - options.position.x, - y: viewCenter.y - options.position.y - }; - this.targetTranslation = { - x: this.sourceTranslation.x + distanceFromCenter.x * this.targetScale + options.offset.x, - y: this.sourceTranslation.y + distanceFromCenter.y * this.targetScale + options.offset.y - }; - - // if the time is set to 0, don't do an animation - if (options.animation.duration == 0) { - if (this.lockedOnNodeId != null) { - this._classicRedraw = this._redraw; - this._redraw = this._lockedRedraw; - } - else { - this._setScale(this.targetScale); - this._setTranslation(this.targetTranslation.x, this.targetTranslation.y); - this._redraw(); + else if (!this.selected && this.dom.dragRight) { + // delete drag area + if (this.dom.dragRight.parentNode) { + this.dom.dragRight.parentNode.removeChild(this.dom.dragRight); } - } - else { - this.animating = true; - this.animationSpeed = 1 / (this.renderRefreshRate * options.animation.duration * 0.001) || 1 / this.renderRefreshRate; - this.animationEasingFunction = options.animation.easingFunction; - this._classicRedraw = this._redraw; - this._redraw = this._transitionRedraw; - this._redraw(); - this.start(); + this.dom.dragRight = null; } }; + module.exports = RangeItem; + + +/***/ }, +/* 31 */ +/***/ function(module, exports, __webpack_require__) { + + var Hammer = __webpack_require__(19); + var util = __webpack_require__(1); + /** - * used to animate smoothly by hijacking the redraw function. - * @private + * @constructor Item + * @param {Object} data Object containing (optional) parameters type, + * start, end, content, group, className. + * @param {{toScreen: function, toTime: function}} conversion + * Conversion functions from time to screen and vice versa + * @param {Object} options Configuration options + * // TODO: describe available options */ - Network.prototype._lockedRedraw = function () { - var nodePosition = {x: this.nodes[this.lockedOnNodeId].x, y: this.nodes[this.lockedOnNodeId].y}; - var viewCenter = this.DOMtoCanvas({x: 0.5 * this.frame.canvas.clientWidth, y: 0.5 * this.frame.canvas.clientHeight}); - var distanceFromCenter = { // offset from view, distance view has to change by these x and y to center the node - x: viewCenter.x - nodePosition.x, - y: viewCenter.y - nodePosition.y - }; - var sourceTranslation = this._getTranslation(); - var targetTranslation = { - x: sourceTranslation.x + distanceFromCenter.x * this.scale + this.lockedOnNodeOffset.x, - y: sourceTranslation.y + distanceFromCenter.y * this.scale + this.lockedOnNodeOffset.y - }; + function Item (data, conversion, options) { + this.id = null; + this.parent = null; + this.data = data; + this.dom = null; + this.conversion = conversion || {}; + this.options = options || {}; - this._setTranslation(targetTranslation.x,targetTranslation.y); - this._classicRedraw(); - } + this.selected = false; + this.displayed = false; + this.dirty = true; - Network.prototype.releaseNode = function () { - if (this.lockedOnNodeId != null) { - this._redraw = this._classicRedraw; - this.lockedOnNodeId = null; - this.lockedOnNodeOffset = null; - } + this.top = null; + this.left = null; + this.width = null; + this.height = null; } + Item.prototype.stack = true; + /** - * - * @param easingTime - * @private + * Select current item */ - Network.prototype._transitionRedraw = function (easingTime) { - this.easingTime = easingTime || this.easingTime + this.animationSpeed; - this.easingTime += this.animationSpeed; - - var progress = util.easingFunctions[this.animationEasingFunction](this.easingTime); + Item.prototype.select = function() { + this.selected = true; + this.dirty = true; + if (this.displayed) this.redraw(); + }; - this._setScale(this.sourceScale + (this.targetScale - this.sourceScale) * progress); - this._setTranslation( - this.sourceTranslation.x + (this.targetTranslation.x - this.sourceTranslation.x) * progress, - this.sourceTranslation.y + (this.targetTranslation.y - this.sourceTranslation.y) * progress - ); + /** + * Unselect current item + */ + Item.prototype.unselect = function() { + this.selected = false; + this.dirty = true; + if (this.displayed) this.redraw(); + }; - this._classicRedraw(); + /** + * Set data for the item. Existing data will be updated. The id should not + * be changed. When the item is displayed, it will be redrawn immediately. + * @param {Object} data + */ + Item.prototype.setData = function(data) { + this.data = data; + this.dirty = true; + if (this.displayed) this.redraw(); + }; - // cleanup - if (this.easingTime >= 1.0) { - this.animating = false; - this.easingTime = 0; - if (this.lockedOnNodeId != null) { - this._redraw = this._lockedRedraw; - } - else { - this._redraw = this._classicRedraw; + /** + * Set a parent for the item + * @param {ItemSet | Group} parent + */ + Item.prototype.setParent = function(parent) { + if (this.displayed) { + this.hide(); + this.parent = parent; + if (this.parent) { + this.show(); } - this.emit("animationFinished"); + } + else { + this.parent = parent; } }; - Network.prototype._classicRedraw = function () { - // placeholder function to be overloaded by animations; + /** + * Check whether this item is visible inside given range + * @returns {{start: Number, end: Number}} range with a timestamp for start and end + * @returns {boolean} True if visible + */ + Item.prototype.isVisible = function(range) { + // Should be implemented by Item implementations + return false; }; /** - * Returns true when the Network is active. - * @returns {boolean} + * Show the Item in the DOM (when not already visible) + * @return {Boolean} changed */ - Network.prototype.isActive = function () { - return !this.activator || this.activator.active; + Item.prototype.show = function() { + return false; }; - /** - * Sets the scale - * @returns {Number} + * Hide the Item from the DOM (when visible) + * @return {Boolean} changed */ - Network.prototype.setScale = function () { - return this._setScale(); + Item.prototype.hide = function() { + return false; }; - /** - * Returns the scale - * @returns {Number} + * Repaint the item */ - Network.prototype.getScale = function () { - return this._getScale(); + Item.prototype.redraw = function() { + // should be implemented by the item }; - /** - * Returns the scale - * @returns {Number} + * Reposition the Item horizontally */ - Network.prototype.getCenterCoordinates = function () { - return this.DOMtoCanvas({x: 0.5 * this.frame.canvas.clientWidth, y: 0.5 * this.frame.canvas.clientHeight}); + Item.prototype.repositionX = function() { + // should be implemented by the item }; + /** + * Reposition the Item vertically + */ + Item.prototype.repositionY = function() { + // should be implemented by the item + }; - Network.prototype.getBoundingBox = function(nodeId) { - if (this.nodes[nodeId] !== undefined) { - return this.nodes[nodeId].boundingBox; - } - } + /** + * Repaint a delete button on the top right of the item when the item is selected + * @param {HTMLElement} anchor + * @protected + */ + Item.prototype._repaintDeleteButton = function (anchor) { + if (this.selected && this.options.editable.remove && !this.dom.deleteButton) { + // create and show button + var me = this; - Network.prototype.getConnectedNodes = function(nodeId) { - var nodeList = []; - if (this.nodes[nodeId] !== undefined) { - var node = this.nodes[nodeId]; - var nodeObj = {nodeId : true}; // used to quickly check if node already exists - for (var i = 0; i < node.edges.length; i++) { - var edge = node.edges[i]; - if (edge.toId == nodeId) { - if (nodeObj[edge.fromId] === undefined) { - nodeList.push(edge.fromId); - nodeObj[edge.fromId] = true; - } - } - else if (edge.fromId == nodeId) { - if (nodeObj[edge.toId] === undefined) { - nodeList.push(edge.toId) - nodeObj[edge.toId] = true; - } - } - } - } - return nodeList; - } + var deleteButton = document.createElement('div'); + deleteButton.className = 'delete'; + deleteButton.title = 'Delete this item'; + Hammer(deleteButton, { + preventDefault: true + }).on('tap', function (event) { + me.parent.removeFromDataSet(me); + event.stopPropagation(); + }); - Network.prototype.getEdgesFromNode = function(nodeId) { - var edgesList = []; - if (this.nodes[nodeId] !== undefined) { - var node = this.nodes[nodeId]; - for (var i = 0; i < node.edges.length; i++) { - edgesList.push(node.edges[i].id); + 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; } - return edgesList; - } - - Network.prototype.generateColorObject = function(color) { - return util.parseColor(color); - - } - - module.exports = Network; + }; + /** + * Set HTML contents for the item + * @param {Element} element HTML element to fill with the contents + * @private + */ + Item.prototype._updateContents = function (element) { + var content; + if (this.options.template) { + var itemData = this.parent.itemSet.itemsData.get(this.id); // get a clone of the data from the dataset + content = this.options.template(itemData); + } + else { + content = this.data.content; + } -/***/ }, -/* 37 */ -/***/ function(module, exports, __webpack_require__) { + if(content !== this.content) { + // only replace the content when changed + if (content instanceof Element) { + element.innerHTML = ''; + element.appendChild(content); + } + else if (content != undefined) { + element.innerHTML = content; + } + else { + if (!(this.data.type == 'background' && this.data.content === undefined)) { + throw new Error('Property "content" missing in item ' + this.id); + } + } - var util = __webpack_require__(1); - var Node = __webpack_require__(40); + this.content = content; + } + }; /** - * @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 + * Set HTML contents for the item + * @param {Element} element HTML element to fill with the contents + * @private */ - function Edge (properties, network, networkConstants) { - if (!network) { - throw "No network provided"; + Item.prototype._updateTitle = function (element) { + if (this.data.title != null) { + element.title = this.data.title || ''; } - var fields = ['edges','physics']; - var constants = util.selectiveBridgeObject(fields,networkConstants); - this.options = constants.edges; - this.physics = constants.physics; - this.options['smoothCurves'] = networkConstants['smoothCurves']; - + else { + element.removeAttribute('title'); + } + }; - this.network = network; + /** + * Process dataAttributes timeline option and set as data- attributes on dom.content + * @param {Element} element HTML element to which the attributes will be attached + * @private + */ + Item.prototype._updateDataAttributes = function(element) { + if (this.options.dataAttributes && this.options.dataAttributes.length > 0) { + var attributes = []; - // initialize variables - this.id = undefined; - this.fromId = undefined; - this.toId = undefined; - this.title = undefined; - this.widthSelected = this.options.width * this.options.widthSelectionMultiplier; - this.value = undefined; - this.selected = false; - this.hover = false; - this.labelDimensions = {top:0,left:0,width:0,height:0,yLine:0}; // could be cached - this.dirtyLabel = true; - this.colorDirty = true; + if (Array.isArray(this.options.dataAttributes)) { + attributes = this.options.dataAttributes; + } + else if (this.options.dataAttributes == 'all') { + attributes = Object.keys(this.data); + } + else { + return; + } - this.from = null; // a node - this.to = null; // a node - this.via = null; // a temp node + for (var i = 0; i < attributes.length; i++) { + var name = attributes[i]; + var value = this.data[name]; - this.fromBackup = null; // used to clean up after reconnect - this.toBackup = null;; // used to clean up after reconnect + if (value != null) { + element.setAttribute('data-' + name, value); + } + else { + element.removeAttribute('data-' + name); + } + } + } + }; - // 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 = []; + /** + * Update custom styles of the element + * @param element + * @private + */ + Item.prototype._updateStyle = function(element) { + // remove old styles + if (this.style) { + util.removeCssText(element, this.style); + this.style = null; + } - this.connected = false; + // append new styles + if (this.data.style) { + util.addCssText(element, this.data.style); + this.style = this.data.style; + } + }; - this.widthFixed = false; - this.lengthFixed = false; + module.exports = Item; - this.setProperties(properties); - this.controlNodesEnabled = false; - this.controlNodes = {from:null, to:null, positions:{}}; - this.connectedNode = null; - } +/***/ }, +/* 32 */ +/***/ function(module, exports, __webpack_require__) { + + var util = __webpack_require__(1); + var Group = __webpack_require__(28); /** - * Set or overwrite properties for the edge - * @param {Object} properties an object with properties - * @param {Object} constants and object with default, global properties + * @constructor BackgroundGroup + * @param {Number | String} groupId + * @param {Object} data + * @param {ItemSet} itemSet */ - Edge.prototype.setProperties = function(properties) { - this.colorDirty = true; - if (!properties) { - return; - } - - var fields = ['style','fontSize','fontFace','fontColor','fontFill','fontStrokeWidth','fontStrokeColor','width', - 'widthSelectionMultiplier','hoverWidth','arrowScaleFactor','dash','inheritColor','labelAlignment', 'opacity', - 'customScalingFunction','useGradients' - ]; - util.selectiveDeepExtend(fields, this.options, properties); - - if (properties.from !== undefined) {this.fromId = properties.from;} - if (properties.to !== undefined) {this.toId = properties.to;} + function BackgroundGroup (groupId, data, itemSet) { + Group.call(this, groupId, data, itemSet); - if (properties.id !== undefined) {this.id = properties.id;} - if (properties.label !== undefined) {this.label = properties.label; this.dirtyLabel = true;} + this.width = 0; + this.height = 0; + this.top = 0; + this.left = 0; + } - if (properties.title !== undefined) {this.title = properties.title;} - if (properties.value !== undefined) {this.value = properties.value;} - if (properties.length !== undefined) {this.physics.springLength = properties.length;} + BackgroundGroup.prototype = Object.create(Group.prototype); - if (properties.color !== undefined) { - this.options.inheritColor = false; - if (util.isString(properties.color)) { - this.options.color.color = properties.color; - this.options.color.highlight = properties.color; - } - else { - if (properties.color.color !== undefined) {this.options.color.color = properties.color.color;} - if (properties.color.highlight !== undefined) {this.options.color.highlight = properties.color.highlight;} - if (properties.color.hover !== undefined) {this.options.color.hover = properties.color.hover;} - } - } + /** + * 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 + */ + BackgroundGroup.prototype.redraw = function(range, margin, restack) { + var resized = false; + this.visibleItems = this._updateVisibleItems(this.orderedItems, this.visibleItems, range); + // calculate actual size + this.width = this.dom.background.offsetWidth; - // A node is connected when it has a from and to node. - this.connect(); + // apply new height (just always zero for BackgroundGroup + this.dom.background.style.height = '0'; - this.widthFixed = this.widthFixed || (properties.width !== undefined); - this.lengthFixed = this.lengthFixed || (properties.length !== undefined); + // 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(margin); + } - this.widthSelected = this.options.width* this.options.widthSelectionMultiplier; + return resized; + }; - // set draw method based on style - switch (this.options.style) { - case 'line': this.draw = this._drawLine; break; - case 'arrow': this.draw = this._drawArrow; break; - case 'arrow-center': this.draw = this._drawArrowCenter; break; - case 'dash-line': this.draw = this._drawDashLine; break; - default: this.draw = this._drawLine; break; + /** + * Show this group: attach to the DOM + */ + BackgroundGroup.prototype.show = function() { + if (!this.dom.background.parentNode) { + this.itemSet.dom.background.appendChild(this.dom.background); } }; + module.exports = BackgroundGroup; - /** - * 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); +/***/ }, +/* 33 */ +/***/ function(module, exports, __webpack_require__) { - if (this.connected) { - this.from.attachEdge(this); - this.to.attachEdge(this); - } - else { - if (this.from) { - this.from.detachEdge(this); + var Item = __webpack_require__(31); + var util = __webpack_require__(1); + + /** + * @constructor BoxItem + * @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 BoxItem (data, conversion, options) { + this.props = { + dot: { + width: 0, + height: 0 + }, + line: { + width: 0, + height: 0 } - if (this.to) { - this.to.detachEdge(this); + }; + + // validate data + if (data) { + if (data.start == undefined) { + throw new Error('Property "start" missing in item ' + data); } } + + Item.call(this, data, conversion, options); + } + + BoxItem.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 + */ + BoxItem.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); }; /** - * Disconnect an edge from its nodes + * Repaint the item */ - Edge.prototype.disconnect = function () { - if (this.from) { - this.from.detachEdge(this); - this.from = null; + BoxItem.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; + + this.dirty = true; } - if (this.to) { - this.to.detachEdge(this); - this.to = null; + + // append DOM to parent DOM + if (!this.parent) { + throw new Error('Cannot redraw item: no parent attached'); + } + if (!dom.box.parentNode) { + var foreground = this.parent.dom.foreground; + if (!foreground) throw new Error('Cannot redraw item: parent has no foreground container element'); + foreground.appendChild(dom.box); + } + if (!dom.line.parentNode) { + var background = this.parent.dom.background; + if (!background) throw new Error('Cannot redraw item: 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 item: parent has no axis container element'); + axis.appendChild(dom.dot); } + this.displayed = true; - this.connected = false; - }; + // Update DOM when item is marked dirty. An item is marked dirty when: + // - the item is not yet rendered + // - the item's data is changed + // - the item is selected/deselected + if (this.dirty) { + this._updateContents(this.dom.content); + this._updateTitle(this.dom.box); + this._updateDataAttributes(this.dom.box); + this._updateStyle(this.dom.box); - /** - * 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; - }; + // update class + var className = (this.data.className? ' ' + this.data.className : '') + + (this.selected ? ' selected' : ''); + dom.box.className = 'item box' + className; + dom.line.className = 'item line' + className; + dom.dot.className = 'item dot' + className; + // recalculate size + 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; - /** - * Retrieve the value of the edge. Can be undefined - * @return {Number} value - */ - Edge.prototype.getValue = function() { - return this.value; + this.dirty = false; + } + + this._repaintDeleteButton(dom.box); }; /** - * Adjust the value range of the edge. The edge will adjust it's width - * based on its value. - * @param {Number} min - * @param {Number} max + * Show the item in the DOM (when not already displayed). The items DOM will + * be created when needed. */ - Edge.prototype.setValueRange = function(min, max, total) { - if (!this.widthFixed && this.value !== undefined) { - var scale = this.options.customScalingFunction(min, max, total, this.value); - var widthDiff = this.options.widthMax - this.options.widthMin; - this.options.width = this.options.widthMin + scale * widthDiff; - this.widthSelected = this.options.width* this.options.widthSelectionMultiplier; + BoxItem.prototype.show = function() { + if (!this.displayed) { + this.redraw(); } }; /** - * 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 + * Hide the item from the DOM (when visible) */ - Edge.prototype.draw = function(ctx) { - throw "Method draw not initialized in edge"; + BoxItem.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); + + this.top = null; + this.left = null; + + this.displayed = false; + } }; /** - * 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 + * Reposition the item horizontally + * @Override */ - Edge.prototype.isOverlappingWith = function(obj) { - if (this.connected) { - var distMax = 10; - var xFrom = this.from.x; - var yFrom = this.from.y; - var xTo = this.to.x; - var yTo = this.to.y; - var xObj = obj.left; - var yObj = obj.top; - - var dist = this._getDistanceToEdge(xFrom, yFrom, xTo, yTo, xObj, yObj); + BoxItem.prototype.repositionX = function() { + var start = this.conversion.toScreen(this.data.start); + var align = this.options.align; + var left; + var box = this.dom.box; + var line = this.dom.line; + var dot = this.dom.dot; - return (dist < distMax); + // calculate left position of the box + if (align == 'right') { + this.left = start - this.width; + } + else if (align == 'left') { + this.left = start; } else { - return false + // default or 'center' + this.left = start - this.width / 2; } + + // reposition box + box.style.left = this.left + 'px'; + + // reposition line + line.style.left = (start - this.props.line.width / 2) + 'px'; + + // reposition dot + dot.style.left = (start - this.props.dot.width / 2) + 'px'; }; - Edge.prototype._getColor = function(ctx) { - var colorObj = this.options.color; - if (this.options.useGradients == true) { - var grd = ctx.createLinearGradient(this.from.x, this.from.y, this.to.x, this.to.y); - var fromColor, toColor; - fromColor = this.from.options.color.highlight.border; - toColor = this.to.options.color.highlight.border; + /** + * Reposition the item vertically + * @Override + */ + BoxItem.prototype.repositionY = function() { + var orientation = this.options.orientation; + var box = this.dom.box; + var line = this.dom.line; + var dot = this.dom.dot; + if (orientation == 'top') { + box.style.top = (this.top || 0) + 'px'; - if (this.from.selected == false && this.to.selected == false) { - fromColor = util.overrideOpacity(this.from.options.color.border, this.options.opacity); - toColor = util.overrideOpacity(this.to.options.color.border, this.options.opacity); - } - else if (this.from.selected == true && this.to.selected == false) { - toColor = this.to.options.color.border; - } - else if (this.from.selected == false && this.to.selected == true) { - fromColor = this.from.options.color.border; - } - grd.addColorStop(0, fromColor); - grd.addColorStop(1, toColor); - return grd; + 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; - if (this.colorDirty === true) { - if (this.options.inheritColor == "to") { - colorObj = { - highlight: this.to.options.color.highlight.border, - hover: this.to.options.color.hover.border, - color: util.overrideOpacity(this.from.options.color.border, this.options.opacity) - }; - } - else if (this.options.inheritColor == "from" || this.options.inheritColor == true) { - colorObj = { - highlight: this.from.options.color.highlight.border, - hover: this.from.options.color.hover.border, - color: util.overrideOpacity(this.from.options.color.border, this.options.opacity) - }; - } - this.options.color = colorObj; - this.colorDirty = false; + box.style.top = (this.parent.height - this.top - this.height || 0) + 'px'; + line.style.top = (itemSetHeight - lineHeight) + 'px'; + line.style.bottom = '0'; } + dot.style.top = (-this.props.dot.height / 2) + 'px'; + }; + module.exports = BoxItem; - if (this.selected == true) {return colorObj.highlight;} - else if (this.hover == true) {return colorObj.hover;} - else {return colorObj.color;} - }; +/***/ }, +/* 34 */ +/***/ function(module, exports, __webpack_require__) { + + var Item = __webpack_require__(31); /** - * 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 + * @constructor PointItem + * @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 */ - Edge.prototype._drawLine = function(ctx) { - // set style - ctx.strokeStyle = this._getColor(ctx); - ctx.lineWidth = this._getLineWidth(); + function PointItem (data, conversion, options) { + this.props = { + dot: { + top: 0, + width: 0, + height: 0 + }, + content: { + height: 0, + marginLeft: 0 + } + }; - if (this.from != this.to) { - // draw line - var via = this._line(ctx); + // validate data + if (data) { + if (data.start == undefined) { + throw new Error('Property "start" missing in item ' + data); + } + } - // draw label - var point; - if (this.label) { - if (this.options.smoothCurves.enabled == true && via != null) { - var midpointX = 0.5*(0.5*(this.from.x + via.x) + 0.5*(this.to.x + via.x)); - var midpointY = 0.5*(0.5*(this.from.y + via.y) + 0.5*(this.to.y + via.y)); - point = {x:midpointX, y:midpointY}; - } - else { - point = this._pointOnLine(0.5); - } - this._label(ctx, this.label, point.x, point.y); - } - } - else { - var x, y; - var radius = this.physics.springLength / 4; - var node = this.from; - if (!node.width) { - node.resize(ctx); - } - if (node.width > node.height) { - x = node.x + node.width / 2; - y = node.y - radius; - } - else { - x = node.x + radius; - y = node.y - node.height / 2; - } - this._circle(ctx, x, y, radius); - point = this._pointOnCircle(x, y, radius, 0.5); - this._label(ctx, this.label, point.x, point.y); - } - }; + Item.call(this, data, conversion, options); + } + + PointItem.prototype = new Item (null, null, null); /** - * Get the line width of the edge. Depends on width and whether one of the - * connected nodes is selected. - * @return {Number} width - * @private + * 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 */ - Edge.prototype._getLineWidth = function() { - if (this.selected == true) { - return Math.max(Math.min(this.widthSelected, this.options.widthMax), 0.3*this.networkScaleInv); - } - else { - if (this.hover == true) { - return Math.max(Math.min(this.options.hoverWidth, this.options.widthMax), 0.3*this.networkScaleInv); - } - else { - return Math.max(this.options.width, 0.3*this.networkScaleInv); - } - } + PointItem.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); }; - Edge.prototype._getViaCoordinates = function () { - if (this.options.smoothCurves.dynamic == true && this.options.smoothCurves.enabled == true ) { - return this.via; + /** + * Repaint the item + */ + PointItem.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; + + this.dirty = true; } - else if (this.options.smoothCurves.enabled == false) { - return {x:0,y:0}; + + // append DOM to parent DOM + if (!this.parent) { + throw new Error('Cannot redraw item: no parent attached'); } - else { - var xVia = null; - var yVia = null; - var factor = this.options.smoothCurves.roundness; - var type = this.options.smoothCurves.type; - var dx = Math.abs(this.from.x - this.to.x); - var dy = Math.abs(this.from.y - this.to.y); - if (type == 'discrete' || type == 'diagonalCross') { - if (Math.abs(this.from.x - this.to.x) < Math.abs(this.from.y - this.to.y)) { - if (this.from.y > this.to.y) { - if (this.from.x < this.to.x) { - xVia = this.from.x + factor * dy; - yVia = this.from.y - factor * dy; - } - else if (this.from.x > this.to.x) { - xVia = this.from.x - factor * dy; - yVia = this.from.y - factor * dy; - } - } - else if (this.from.y < this.to.y) { - if (this.from.x < this.to.x) { - xVia = this.from.x + factor * dy; - yVia = this.from.y + factor * dy; - } - else if (this.from.x > this.to.x) { - xVia = this.from.x - factor * dy; - yVia = this.from.y + factor * dy; - } - } - if (type == "discrete") { - xVia = dx < factor * dy ? this.from.x : xVia; - } - } - else if (Math.abs(this.from.x - this.to.x) > Math.abs(this.from.y - this.to.y)) { - if (this.from.y > this.to.y) { - if (this.from.x < this.to.x) { - xVia = this.from.x + factor * dx; - yVia = this.from.y - factor * dx; - } - else if (this.from.x > this.to.x) { - xVia = this.from.x - factor * dx; - yVia = this.from.y - factor * dx; - } - } - else if (this.from.y < this.to.y) { - if (this.from.x < this.to.x) { - xVia = this.from.x + factor * dx; - yVia = this.from.y + factor * dx; - } - else if (this.from.x > this.to.x) { - xVia = this.from.x - factor * dx; - yVia = this.from.y + factor * dx; - } - } - if (type == "discrete") { - yVia = dy < factor * dx ? this.from.y : yVia; - } - } - } - else if (type == "straightCross") { - if (Math.abs(this.from.x - this.to.x) < Math.abs(this.from.y - this.to.y)) { // up - down - xVia = this.from.x; - if (this.from.y < this.to.y) { - yVia = this.to.y - (1 - factor) * dy; - } - else { - yVia = this.to.y + (1 - factor) * dy; - } - } - else if (Math.abs(this.from.x - this.to.x) > Math.abs(this.from.y - this.to.y)) { // left - right - if (this.from.x < this.to.x) { - xVia = this.to.x - (1 - factor) * dx; - } - else { - xVia = this.to.x + (1 - factor) * dx; - } - yVia = this.from.y; - } - } - else if (type == 'horizontal') { - if (this.from.x < this.to.x) { - xVia = this.to.x - (1 - factor) * dx; - } - else { - xVia = this.to.x + (1 - factor) * dx; - } - yVia = this.from.y; - } - else if (type == 'vertical') { - xVia = this.from.x; - if (this.from.y < this.to.y) { - yVia = this.to.y - (1 - factor) * dy; - } - else { - yVia = this.to.y + (1 - factor) * dy; - } + if (!dom.point.parentNode) { + var foreground = this.parent.dom.foreground; + if (!foreground) { + throw new Error('Cannot redraw item: parent has no foreground container element'); } - else if (type == 'curvedCW') { - var dx = this.to.x - this.from.x; - var dy = this.from.y - this.to.y; - var radius = Math.sqrt(dx*dx + dy*dy); - var pi = Math.PI; + foreground.appendChild(dom.point); + } + this.displayed = true; - var originalAngle = Math.atan2(dy,dx); - var myAngle = (originalAngle + ((factor * 0.5) + 0.5) * pi) % (2 * pi); + // Update DOM when item is marked dirty. An item is marked dirty when: + // - the item is not yet rendered + // - the item's data is changed + // - the item is selected/deselected + if (this.dirty) { + this._updateContents(this.dom.content); + this._updateTitle(this.dom.point); + this._updateDataAttributes(this.dom.point); + this._updateStyle(this.dom.point); - xVia = this.from.x + (factor*0.5 + 0.5)*radius*Math.sin(myAngle); - yVia = this.from.y + (factor*0.5 + 0.5)*radius*Math.cos(myAngle); - } - else if (type == 'curvedCCW') { - var dx = this.to.x - this.from.x; - var dy = this.from.y - this.to.y; - var radius = Math.sqrt(dx*dx + dy*dy); - var pi = Math.PI; + // update class + var className = (this.data.className? ' ' + this.data.className : '') + + (this.selected ? ' selected' : ''); + dom.point.className = 'item point' + className; + dom.dot.className = 'item dot' + className; - var originalAngle = Math.atan2(dy,dx); - var myAngle = (originalAngle + ((-factor * 0.5) + 0.5) * pi) % (2 * pi); + // recalculate size + 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; - xVia = this.from.x + (factor*0.5 + 0.5)*radius*Math.sin(myAngle); - yVia = this.from.y + (factor*0.5 + 0.5)*radius*Math.cos(myAngle); - } - else { // continuous - if (Math.abs(this.from.x - this.to.x) < Math.abs(this.from.y - this.to.y)) { - if (this.from.y > this.to.y) { - if (this.from.x < this.to.x) { - xVia = this.from.x + factor * dy; - yVia = this.from.y - factor * dy; - xVia = this.to.x < xVia ? this.to.x : xVia; - } - else if (this.from.x > this.to.x) { - xVia = this.from.x - factor * dy; - yVia = this.from.y - factor * dy; - xVia = this.to.x > xVia ? this.to.x : xVia; - } - } - else if (this.from.y < this.to.y) { - if (this.from.x < this.to.x) { - xVia = this.from.x + factor * dy; - yVia = this.from.y + factor * dy; - xVia = this.to.x < xVia ? this.to.x : xVia; - } - else if (this.from.x > this.to.x) { - xVia = this.from.x - factor * dy; - yVia = this.from.y + factor * dy; - xVia = this.to.x > xVia ? this.to.x : xVia; - } - } - } - else if (Math.abs(this.from.x - this.to.x) > Math.abs(this.from.y - this.to.y)) { - if (this.from.y > this.to.y) { - if (this.from.x < this.to.x) { - xVia = this.from.x + factor * dx; - yVia = this.from.y - factor * dx; - yVia = this.to.y > yVia ? this.to.y : yVia; - } - else if (this.from.x > this.to.x) { - xVia = this.from.x - factor * dx; - yVia = this.from.y - factor * dx; - yVia = this.to.y > yVia ? this.to.y : yVia; - } - } - else if (this.from.y < this.to.y) { - if (this.from.x < this.to.x) { - xVia = this.from.x + factor * dx; - yVia = this.from.y + factor * dx; - yVia = this.to.y < yVia ? this.to.y : yVia; - } - else if (this.from.x > this.to.x) { - xVia = this.from.x - factor * dx; - yVia = this.from.y + factor * dx; - yVia = this.to.y < yVia ? this.to.y : yVia; - } - } - } - } + // 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'; - return {x: xVia, y: yVia}; + this.dirty = 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.options.smoothCurves.enabled == true) { - if (this.options.smoothCurves.dynamic == false) { - var via = this._getViaCoordinates(); - if (via.x == null) { - ctx.lineTo(this.to.x, this.to.y); - ctx.stroke(); - return null; - } - else { - // this.via.x = via.x; - // this.via.y = via.y; - ctx.quadraticCurveTo(via.x,via.y,this.to.x, this.to.y); - ctx.stroke(); - //ctx.circle(via.x,via.y,2) - //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; - } + this._repaintDeleteButton(dom.point); }; /** - * Draw a line from a node to itself, a circle - * @param {CanvasRenderingContext2D} ctx - * @param {Number} x - * @param {Number} y - * @param {Number} radius - * @private + * Show the item in the DOM (when not already visible). The items DOM will + * be created when needed. */ - 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(); + PointItem.prototype.show = function() { + if (!this.displayed) { + this.redraw(); + } }; /** - * 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 + * Hide the item from the DOM (when visible) */ - Edge.prototype._label = function (ctx, text, x, y) { - if (text) { - ctx.font = ((this.from.selected || this.to.selected) ? "bold " : "") + - this.options.fontSize + "px " + this.options.fontFace; - var yLine; - - if (this.dirtyLabel == true) { - var lines = String(text).split('\n'); - var lineCount = lines.length; - var fontSize = Number(this.options.fontSize); - yLine = y + (1 - lineCount) / 2 * fontSize; - - var width = ctx.measureText(lines[0]).width; - for (var i = 1; i < lineCount; i++) { - var lineWidth = ctx.measureText(lines[i]).width; - width = lineWidth > width ? lineWidth : width; - } - var height = this.options.fontSize * lineCount; - var left = x - width / 2; - var top = y - height / 2; - - // cache - this.labelDimensions = {top:top,left:left,width:width,height:height,yLine:yLine}; + PointItem.prototype.hide = function() { + if (this.displayed) { + if (this.dom.point.parentNode) { + this.dom.point.parentNode.removeChild(this.dom.point); } - var yLine = this.labelDimensions.yLine; - - ctx.save(); - - if (this.options.labelAlignment != "horizontal"){ - ctx.translate(x, yLine); - this._rotateForLabelAlignment(ctx); - x = 0; - yLine = 0; - } + this.top = null; + this.left = null; - - this._drawLabelRect(ctx); - this._drawLabelText(ctx,x,yLine, lines, lineCount, fontSize); - - ctx.restore(); + this.displayed = false; } }; /** - * Rotates the canvas so the text is most readable - * @param {CanvasRenderingContext2D} ctx - * @private + * Reposition the item horizontally + * @Override */ - Edge.prototype._rotateForLabelAlignment = function(ctx) { - var dy = this.from.y - this.to.y; - var dx = this.from.x - this.to.x; - var angleInDegrees = Math.atan2(dy, dx); + PointItem.prototype.repositionX = function() { + var start = this.conversion.toScreen(this.data.start); - // rotate so label it is readable - if((angleInDegrees < -1 && dx < 0) || (angleInDegrees > 0 && dx < 0)){ - angleInDegrees = angleInDegrees + Math.PI; - } - - ctx.rotate(angleInDegrees); + this.left = start - this.props.dot.width; + + // reposition point + this.dom.point.style.left = this.left + 'px'; }; /** - * Draws the label rectangle - * @param {CanvasRenderingContext2D} ctx - * @param {String} labelAlignment - * @private + * Reposition the item vertically + * @Override */ - Edge.prototype._drawLabelRect = function(ctx) { - if (this.options.fontFill !== undefined && this.options.fontFill !== null && this.options.fontFill !== "none") { - ctx.fillStyle = this.options.fontFill; - - var lineMargin = 2; + PointItem.prototype.repositionY = function() { + var orientation = this.options.orientation, + point = this.dom.point; - if (this.options.labelAlignment == 'line-center') { - ctx.fillRect(-this.labelDimensions.width * 0.5, -this.labelDimensions.height * 0.5, this.labelDimensions.width, this.labelDimensions.height); - } - else if (this.options.labelAlignment == 'line-above') { - ctx.fillRect(-this.labelDimensions.width * 0.5, -(this.labelDimensions.height + lineMargin), this.labelDimensions.width, this.labelDimensions.height); - } - else if (this.options.labelAlignment == 'line-below') { - ctx.fillRect(-this.labelDimensions.width * 0.5, lineMargin, this.labelDimensions.width, this.labelDimensions.height); - } - else { - ctx.fillRect(this.labelDimensions.left, this.labelDimensions.top, this.labelDimensions.width, this.labelDimensions.height); - } + if (orientation == 'top') { + point.style.top = this.top + 'px'; + } + else { + point.style.top = (this.parent.height - this.top - this.height) + 'px'; } }; + module.exports = PointItem; + + +/***/ }, +/* 35 */ +/***/ function(module, exports, __webpack_require__) { + + var Hammer = __webpack_require__(19); + var Item = __webpack_require__(31); + var BackgroundGroup = __webpack_require__(32); + var RangeItem = __webpack_require__(30); + /** - * Draws the label text - * @param {CanvasRenderingContext2D} ctx - * @param {Number} x - * @param {Number} yLine - * @param {Array} lines - * @param {Number} lineCount - * @param {Number} fontSize - * @private + * @constructor BackgroundItem + * @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 */ - Edge.prototype._drawLabelText = function(ctx, x, yLine, lines, lineCount, fontSize) { - // draw text - ctx.fillStyle = this.options.fontColor || "black"; - ctx.textAlign = "center"; - - // check for label alignment - if (this.options.labelAlignment != 'horizontal') { - var lineMargin = 2; - if (this.options.labelAlignment == 'line-above') { - ctx.textBaseline = "alphabetic"; - yLine -= 2 * lineMargin; // distance from edge, required because we use alphabetic. Alphabetic has less difference between browsers + // TODO: implement support for the BackgroundItem just having a start, then being displayed as a sort of an annotation + function BackgroundItem (data, conversion, options) { + this.props = { + content: { + width: 0 } - else if (this.options.labelAlignment == 'line-below') { - ctx.textBaseline = "hanging"; - yLine += 2 * lineMargin;// distance from edge, required because we use hanging. Hanging has less difference between browsers + }; + 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); } - else { - ctx.textBaseline = "middle"; + if (data.end == undefined) { + throw new Error('Property "end" missing in item ' + data.id); } } - else { - ctx.textBaseline = "middle"; - } - // check for strokeWidth - if (this.options.fontStrokeWidth > 0){ - ctx.lineWidth = this.options.fontStrokeWidth; - ctx.strokeStyle = this.options.fontStrokeColor; - ctx.lineJoin = 'round'; - } - for (var i = 0; i < lineCount; i++) { - if(this.options.fontStrokeWidth > 0){ - ctx.strokeText(lines[i], x, yLine); - } - ctx.fillText(lines[i], x, yLine); - yLine += fontSize; - } + Item.call(this, data, conversion, options); + + this.emptyContent = false; + } + + BackgroundItem.prototype = new Item (null, null, null); + + BackgroundItem.prototype.baseClassName = 'item background'; + BackgroundItem.prototype.stack = false; + + /** + * 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 + */ + BackgroundItem.prototype.isVisible = function(range) { + // determine visibility + return (this.data.start < range.end) && (this.data.end > range.start); }; /** - * 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 + * Repaint the item */ - Edge.prototype._drawDashLine = function(ctx) { - // set style - ctx.strokeStyle = this._getColor(ctx); - ctx.lineWidth = this._getLineWidth(); + BackgroundItem.prototype.redraw = function() { + var dom = this.dom; + if (!dom) { + // create DOM + this.dom = {}; + dom = this.dom; - var via = null; - // only firefox and chrome support this method, else we use the legacy one. - if (ctx.setLineDash !== undefined) { - ctx.save(); - // configure the dash pattern - var pattern = [0]; - if (this.options.dash.length !== undefined && this.options.dash.gap !== undefined) { - pattern = [this.options.dash.length,this.options.dash.gap]; - } - else { - pattern = [5,5]; - } + // background box + dom.box = document.createElement('div'); + // className is updated in redraw() - // set dash settings for chrome or firefox - ctx.setLineDash(pattern); - ctx.lineDashOffset = 0; + // contents box + dom.content = document.createElement('div'); + dom.content.className = 'content'; + dom.box.appendChild(dom.content); - // draw the line - via = this._line(ctx); + // Note: we do NOT attach this item as attribute to the DOM, + // such that background items cannot be selected + //dom.box['timeline-item'] = this; - // restore the dash settings. - ctx.setLineDash([0]); - ctx.lineDashOffset = 0; - ctx.restore(); + this.dirty = true; } - else { // unsupporting smooth lines - // draw dashed line - ctx.beginPath(); - ctx.lineCap = 'round'; - if (this.options.dash.altLength !== undefined) //If an alt dash value has been set add to the array this value - { - ctx.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y, - [this.options.dash.length,this.options.dash.gap,this.options.dash.altLength,this.options.dash.gap]); - } - else if (this.options.dash.length !== undefined && this.options.dash.gap !== undefined) //If a dash and gap value has been set add to the array this value - { - ctx.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y, - [this.options.dash.length,this.options.dash.gap]); - } - else //If all else fails draw a line - { - ctx.moveTo(this.from.x, this.from.y); - ctx.lineTo(this.to.x, this.to.y); + + // append DOM to parent DOM + if (!this.parent) { + throw new Error('Cannot redraw item: no parent attached'); + } + if (!dom.box.parentNode) { + var background = this.parent.dom.background; + if (!background) { + throw new Error('Cannot redraw item: parent has no background container element'); } - ctx.stroke(); + background.appendChild(dom.box); } + this.displayed = true; - // draw label - if (this.label) { - var point; - if (this.options.smoothCurves.enabled == true && via != null) { - var midpointX = 0.5*(0.5*(this.from.x + via.x) + 0.5*(this.to.x + via.x)); - var midpointY = 0.5*(0.5*(this.from.y + via.y) + 0.5*(this.to.y + via.y)); - point = {x:midpointX, y:midpointY}; - } - else { - point = this._pointOnLine(0.5); - } - this._label(ctx, this.label, point.x, point.y); + // Update DOM when item is marked dirty. An item is marked dirty when: + // - the item is not yet rendered + // - the item's data is changed + // - the item is selected/deselected + if (this.dirty) { + this._updateContents(this.dom.content); + this._updateTitle(this.dom.content); + this._updateDataAttributes(this.dom.content); + this._updateStyle(this.dom.box); + + // update class + var className = (this.data.className ? (' ' + this.data.className) : '') + + (this.selected ? ' selected' : ''); + dom.box.className = this.baseClassName + className; + + // determine from css whether this box has overflow + this.overflow = window.getComputedStyle(dom.content).overflow !== 'hidden'; + + // recalculate size + this.props.content.width = this.dom.content.offsetWidth; + this.height = 0; // set height zero, so this item will be ignored when stacking items + + this.dirty = false; } }; /** - * Get a point on a line - * @param {Number} percentage. Value between 0 (line start) and 1 (line end) - * @return {Object} point - * @private + * Show the item in the DOM (when not already visible). The items DOM will + * be created when needed. */ - 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 - } - }; + BackgroundItem.prototype.show = RangeItem.prototype.show; /** - * 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 + * Hide the item from the DOM (when visible) + * @return {Boolean} changed */ - 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) - } - }; + BackgroundItem.prototype.hide = RangeItem.prototype.hide; /** - * 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 + * Reposition the item horizontally + * @Override */ - Edge.prototype._drawArrowCenter = function(ctx) { - var point; - // set style - ctx.strokeStyle = this._getColor(ctx); - ctx.fillStyle = ctx.strokeStyle; - ctx.lineWidth = this._getLineWidth(); + BackgroundItem.prototype.repositionX = RangeItem.prototype.repositionX; - if (this.from != this.to) { - // draw line - var via = this._line(ctx); + /** + * Reposition the item vertically + * @Override + */ + BackgroundItem.prototype.repositionY = function(margin) { + var onTop = this.options.orientation === 'top'; + this.dom.content.style.top = onTop ? '' : '0'; + this.dom.content.style.bottom = onTop ? '0' : ''; + var height; - var angle = Math.atan2((this.to.y - this.from.y), (this.to.x - this.from.x)); - var length = (10 + 5 * this.options.width) * this.options.arrowScaleFactor; - // draw an arrow halfway the line - if (this.options.smoothCurves.enabled == true && via != null) { - var midpointX = 0.5*(0.5*(this.from.x + via.x) + 0.5*(this.to.x + via.x)); - var midpointY = 0.5*(0.5*(this.from.y + via.y) + 0.5*(this.to.y + via.y)); - point = {x:midpointX, y:midpointY}; + // special positioning for subgroups + if (this.data.subgroup !== undefined) { + var itemSubgroup = this.data.subgroup; + var subgroups = this.parent.subgroups; + var subgroupIndex = subgroups[itemSubgroup].index; + // if the orientation is top, we need to take the difference in height into account. + if (onTop == true) { + // the first subgroup will have to account for the distance from the top to the first item. + height = this.parent.subgroups[itemSubgroup].height + margin.item.vertical; + height += subgroupIndex == 0 ? margin.axis - 0.5*margin.item.vertical : 0; + var newTop = this.parent.top; + for (var subgroup in subgroups) { + if (subgroups.hasOwnProperty(subgroup)) { + if (subgroups[subgroup].visible == true && subgroups[subgroup].index < subgroupIndex) { + newTop += subgroups[subgroup].height + margin.item.vertical; + } + } + } + + // the others will have to be offset downwards with this same distance. + newTop += subgroupIndex != 0 ? margin.axis - 0.5 * margin.item.vertical : 0; + this.dom.box.style.top = newTop + 'px'; + this.dom.box.style.bottom = ''; } + // and when the orientation is bottom: else { - point = this._pointOnLine(0.5); - } - - ctx.arrow(point.x, point.y, angle, length); - ctx.fill(); - ctx.stroke(); - - // draw label - if (this.label) { - this._label(ctx, this.label, point.x, point.y); + var newTop = this.parent.top; + for (var subgroup in subgroups) { + if (subgroups.hasOwnProperty(subgroup)) { + if (subgroups[subgroup].visible == true && subgroups[subgroup].index > subgroupIndex) { + newTop += subgroups[subgroup].height + margin.item.vertical; + } + } + } + height = this.parent.subgroups[itemSubgroup].height + margin.item.vertical; + this.dom.box.style.top = newTop + 'px'; + this.dom.box.style.bottom = ''; } } + // and in the case of no subgroups: else { - // draw circle - var x, y; - var radius = 0.25 * Math.max(100,this.physics.springLength); - var node = this.from; - if (!node.width) { - node.resize(ctx); - } - if (node.width > node.height) { - x = node.x + node.width * 0.5; - y = node.y - radius; + // we want backgrounds with groups to only show in groups. + if (this.parent instanceof BackgroundGroup) { + // if the item is not in a group: + height = Math.max(this.parent.height, + this.parent.itemSet.body.domProps.center.height, + this.parent.itemSet.body.domProps.centerContainer.height); + this.dom.box.style.top = onTop ? '0' : ''; + this.dom.box.style.bottom = onTop ? '' : '0'; } else { - x = node.x + radius; - y = node.y - node.height * 0.5; - } - this._circle(ctx, x, y, radius); - - // draw all arrows - var angle = 0.2 * Math.PI; - var length = (10 + 5 * this.options.width) * this.options.arrowScaleFactor; - point = this._pointOnCircle(x, y, radius, 0.5); - ctx.arrow(point.x, point.y, angle, length); - ctx.fill(); - ctx.stroke(); - - // draw label - if (this.label) { - point = this._pointOnCircle(x, y, radius, 0.5); - this._label(ctx, this.label, point.x, point.y); + height = this.parent.height; + // same alignment for items when orientation is top or bottom + this.dom.box.style.top = this.parent.top + 'px'; + this.dom.box.style.bottom = ''; } } + this.dom.box.style.height = height + 'px'; }; - Edge.prototype._pointOnBezier = function(t) { - var via = this._getViaCoordinates(); + module.exports = BackgroundItem; - var x = Math.pow(1-t,2)*this.from.x + (2*t*(1 - t))*via.x + Math.pow(t,2)*this.to.x; - var y = Math.pow(1-t,2)*this.from.y + (2*t*(1 - t))*via.y + Math.pow(t,2)*this.to.y; - return {x:x,y:y}; - } +/***/ }, +/* 36 */ +/***/ function(module, exports, __webpack_require__) { + + var keycharm = __webpack_require__(37); + var Emitter = __webpack_require__(11); + var Hammer = __webpack_require__(19); + var util = __webpack_require__(1); /** - * This function uses binary search to look for the point where the bezier curve crosses the border of the node. - * - * @param from - * @param ctx - * @returns {*} - * @private + * Turn an element into an clickToUse element. + * When not active, the element has a transparent overlay. When the overlay is + * clicked, the mode is changed to active. + * When active, the element is displayed with a blue border around it, and + * the interactive contents of the element can be used. When clicked outside + * the element, the elements mode is changed to inactive. + * @param {Element} container + * @constructor */ - Edge.prototype._findBorderPosition = function(from,ctx) { - var maxIterations = 10; - var iteration = 0; - var low = 0; - var high = 1; - var pos,angle,distanceToBorder, distanceToNodes, difference; - var threshold = 0.2; - var node = this.to; - if (from == true) { - node = this.from; - } + function Activator(container) { + this.active = false; - while (low <= high && iteration < maxIterations) { - var middle = (low + high) * 0.5; + this.dom = { + container: container + }; - pos = this._pointOnBezier(middle); - angle = Math.atan2((node.y - pos.y), (node.x - pos.x)); - distanceToBorder = node.distanceToBorder(ctx,angle); - distanceToNodes = Math.sqrt(Math.pow(pos.x-node.x,2) + Math.pow(pos.y-node.y,2)); - difference = distanceToBorder - distanceToNodes; - if (Math.abs(difference) < threshold) { - break; // found - } - else if (difference < 0) { // distance to nodes is larger than distance to border --> t needs to be bigger if we're looking at the to node. - if (from == false) { - low = middle; - } - else { - high = middle; - } - } - else { - if (from == false) { - high = middle; - } - else { - low = middle; - } + this.dom.overlay = document.createElement('div'); + this.dom.overlay.className = 'overlay'; + + this.dom.container.appendChild(this.dom.overlay); + + this.hammer = Hammer(this.dom.overlay, {prevent_default: false}); + this.hammer.on('tap', this._onTapOverlay.bind(this)); + + // block all touch events (except tap) + var me = this; + var events = [ + 'touch', 'pinch', + 'doubletap', 'hold', + 'dragstart', 'drag', 'dragend', + 'mousewheel', 'DOMMouseScroll' // DOMMouseScroll is needed for Firefox + ]; + events.forEach(function (event) { + me.hammer.on(event, function (event) { + event.stopPropagation(); + }); + }); + + // attach a tap event to the window, in order to deactivate when clicking outside the timeline + this.windowHammer = Hammer(window, {prevent_default: false}); + this.windowHammer.on('tap', function (event) { + // deactivate when clicked outside the container + if (!_hasParent(event.target, container)) { + me.deactivate(); } + }); - iteration++; + if (this.keycharm !== undefined) { + this.keycharm.destroy(); } - pos.t = middle; + this.keycharm = keycharm(); - return pos; + // keycharm listener only bounded when active) + this.escListener = this.deactivate.bind(this); + } + + // turn into an event emitter + Emitter(Activator.prototype); + + // The currently active activator + Activator.current = null; + + /** + * Destroy the activator. Cleans up all created DOM and event listeners + */ + Activator.prototype.destroy = function () { + this.deactivate(); + + // remove dom + this.dom.overlay.parentNode.removeChild(this.dom.overlay); + + // cleanup hammer instances + this.hammer = null; + this.windowHammer = null; + // FIXME: cleaning up hammer instances doesn't work (Timeline not removed from memory) }; /** - * 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 + * Activate the element + * Overlay is hidden, element is decorated with a blue shadow border */ - Edge.prototype._drawArrow = function(ctx) { - // set style - ctx.strokeStyle = this._getColor(ctx); - ctx.fillStyle = ctx.strokeStyle; - ctx.lineWidth = this._getLineWidth(); + Activator.prototype.activate = function () { + // we allow only one active activator at a time + if (Activator.current) { + Activator.current.deactivate(); + } + Activator.current = this; - // set vars - var angle, length, arrowPos; + this.active = true; + this.dom.overlay.style.display = 'none'; + util.addClassName(this.dom.container, 'vis-active'); - // if not connected to itself - if (this.from != this.to) { - // draw line - this._line(ctx); + this.emit('change'); + this.emit('activate'); - // draw arrow head - if (this.options.smoothCurves.enabled == true) { - var via = this._getViaCoordinates(); - arrowPos = this._findBorderPosition(false, ctx); - var guidePos = this._pointOnBezier(Math.max(0.0, arrowPos.t - 0.1)) - angle = Math.atan2((arrowPos.y - guidePos.y), (arrowPos.x - guidePos.x)); - } - else { - 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 toBorderDist = this.to.distanceToBorder(ctx, angle); - var toBorderPoint = (edgeSegmentLength - toBorderDist) / edgeSegmentLength; + // ugly hack: bind ESC after emitting the events, as the Network rebinds all + // keyboard events on a 'change' event + this.keycharm.bind('esc', this.escListener); + }; - arrowPos = {}; - arrowPos.x = (1 - toBorderPoint) * this.from.x + toBorderPoint * this.to.x; - arrowPos.y = (1 - toBorderPoint) * this.from.y + toBorderPoint * this.to.y; - } + /** + * Deactivate the element + * Overlay is displayed on top of the element + */ + Activator.prototype.deactivate = function () { + this.active = false; + this.dom.overlay.style.display = ''; + util.removeClassName(this.dom.container, 'vis-active'); + this.keycharm.unbind('esc', this.escListener); - // draw arrow at the end of the line - length = (10 + 5 * this.options.width) * this.options.arrowScaleFactor; - ctx.arrow(arrowPos.x,arrowPos.y, angle, length); - ctx.fill(); - ctx.stroke(); + this.emit('change'); + this.emit('deactivate'); + }; - // draw label - if (this.label) { - var point; - if (this.options.smoothCurves.enabled == true && via != null) { - point = this._pointOnBezier(0.5); - } - 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.physics.springLength); - if (!node.width) { - node.resize(ctx); - } - if (node.width > node.height) { - x = node.x + node.width * 0.5; - y = node.y - radius; - arrow = { - x: x, - y: node.y, - angle: 0.9 * Math.PI - }; - } - else { - x = node.x + radius; - y = node.y - node.height * 0.5; - arrow = { - x: node.x, - y: y, - angle: 0.6 * Math.PI - }; - } - ctx.beginPath(); - // TODO: similarly, for a line without arrows, draw to the border of the nodes instead of the center - ctx.arc(x, y, radius, 0, 2 * Math.PI, false); - ctx.stroke(); - - // draw all arrows - var length = (10 + 5 * this.options.width) * this.options.arrowScaleFactor; - ctx.arrow(arrow.x, arrow.y, arrow.angle, length); - ctx.fill(); - ctx.stroke(); - - // draw label - if (this.label) { - point = this._pointOnCircle(x, y, radius, 0.5); - this._label(ctx, this.label, point.x, point.y); - } - } + /** + * Handle a tap event: activate the container + * @param event + * @private + */ + Activator.prototype._onTapOverlay = function (event) { + // activate the container + this.activate(); + event.stopPropagation(); }; /** - * 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 + * Test whether the element has the requested parent element somewhere in + * its chain of parent nodes. + * @param {HTMLElement} element + * @param {HTMLElement} parent + * @returns {boolean} Returns true when the parent is found somewhere in the + * chain of parent nodes. * @private */ - Edge.prototype._getDistanceToEdge = function (x1,y1, x2,y2, x3,y3) { // x3,y3 is the point - var returnValue = 0; - if (this.from != this.to) { - if (this.options.smoothCurves.enabled == true) { - var xVia, yVia; - if (this.options.smoothCurves.enabled == true && this.options.smoothCurves.dynamic == true) { - xVia = this.via.x; - yVia = this.via.y; - } - else { - var via = this._getViaCoordinates(); - xVia = via.x; - yVia = via.y; - } - var minDistance = 1e9; - var distance; - var i,t,x,y, lastX, lastY; - for (i = 0; i < 10; i++) { - t = 0.1*i; - x = Math.pow(1-t,2)*x1 + (2*t*(1 - t))*xVia + Math.pow(t,2)*x2; - y = Math.pow(1-t,2)*y1 + (2*t*(1 - t))*yVia + Math.pow(t,2)*y2; - if (i > 0) { - distance = this._getDistanceToLine(lastX,lastY,x,y, x3,y3); - minDistance = distance < minDistance ? distance : minDistance; - } - lastX = x; lastY = y; - } - returnValue = minDistance; - } - else { - returnValue = this._getDistanceToLine(x1,y1,x2,y2,x3,y3); - } - } - else { - var x, y, dx, dy; - var radius = 0.25 * this.physics.springLength; - var node = this.from; - if (node.width > node.height) { - x = node.x + 0.5 * node.width; - y = node.y - radius; - } - else { - x = node.x + radius; - y = node.y - 0.5 * node.height; + function _hasParent(element, parent) { + while (element) { + if (element === parent) { + return true } - dx = x - x3; - dy = y - y3; - returnValue = Math.abs(Math.sqrt(dx*dx + dy*dy) - radius); - } - - if (this.labelDimensions.left < x3 && - this.labelDimensions.left + this.labelDimensions.width > x3 && - this.labelDimensions.top < y3 && - this.labelDimensions.top + this.labelDimensions.height > y3) { - return 0; - } - else { - return returnValue; - } - }; - - 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; + element = element.parentNode; } + return false; + } - var x = x1 + u * px, - y = y1 + u * py, - dx = x - x3, - dy = y - y3; + module.exports = Activator; - //# Note: If the actual distance does not matter, - //# if you only want to compare what this function - //# returns to other results of this function, you - //# can just return the squared distance instead - //# (i.e. remove the sqrt) to gain a little performance - return Math.sqrt(dx*dx + dy*dy); - }; +/***/ }, +/* 37 */ +/***/ function(module, exports, __webpack_require__) { + var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;"use strict"; /** - * This allows the zoom level of the network to influence the rendering - * - * @param scale + * Created by Alex on 11/6/2014. */ - Edge.prototype.setScale = function(scale) { - this.networkScaleInv = 1.0/scale; - }; + // https://github.com/umdjs/umd/blob/master/returnExports.js#L40-L60 + // if the module has no dependencies, the above pattern can be simplified to + (function (root, factory) { + if (true) { + // AMD. Register as an anonymous module. + !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + } else if (typeof exports === 'object') { + // Node. Does not work with strict CommonJS, but + // only CommonJS-like environments that support module.exports, + // like Node. + module.exports = factory(); + } else { + // Browser globals (root is window) + root.keycharm = factory(); + } + }(this, function () { - Edge.prototype.select = function() { - this.selected = true; - }; + function keycharm(options) { + var preventDefault = options && options.preventDefault || false; - Edge.prototype.unselect = function() { - this.selected = false; - }; + var container = options && options.container || window; + var _exportFunctions = {}; + var _bound = {keydown:{}, keyup:{}}; + var _keys = {}; + var i; - Edge.prototype.positionBezierNode = function() { - if (this.via !== null && this.from !== null && this.to !== null) { - this.via.x = 0.5 * (this.from.x + this.to.x); - this.via.y = 0.5 * (this.from.y + this.to.y); - } - else if (this.via !== null) { - this.via.x = 0; - this.via.y = 0; - } - }; + // a - z + for (i = 97; i <= 122; i++) {_keys[String.fromCharCode(i)] = {code:65 + (i - 97), shift: false};} + // A - Z + for (i = 65; i <= 90; i++) {_keys[String.fromCharCode(i)] = {code:i, shift: true};} + // 0 - 9 + for (i = 0; i <= 9; i++) {_keys['' + i] = {code:48 + i, shift: false};} + // F1 - F12 + for (i = 1; i <= 12; i++) {_keys['F' + i] = {code:111 + i, shift: false};} + // num0 - num9 + for (i = 0; i <= 9; i++) {_keys['num' + i] = {code:96 + i, shift: false};} - /** - * 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:7, borderWidth:2, borderWidthSelected: 2}, - physics:{damping:0}, - clustering: {maxNodeSizeIncrements: 0 ,nodeScaling: {width:0, height: 0, radius:0}} - }; - this.controlNodes.from = new Node( - {id:nodeIdFrom, - shape:'dot', - color:{background:'#ff0000', border:'#3c3c3c', highlight: {background:'#07f968'}} - },{},{},constants); - this.controlNodes.to = new Node( - {id:nodeIdTo, - shape:'dot', - color:{background:'#ff0000', border:'#3c3c3c', highlight: {background:'#07f968'}} - },{},{},constants); - } + // numpad misc + _keys['num*'] = {code:106, shift: false}; + _keys['num+'] = {code:107, shift: false}; + _keys['num-'] = {code:109, shift: false}; + _keys['num/'] = {code:111, shift: false}; + _keys['num.'] = {code:110, shift: false}; + // arrows + _keys['left'] = {code:37, shift: false}; + _keys['up'] = {code:38, shift: false}; + _keys['right'] = {code:39, shift: false}; + _keys['down'] = {code:40, shift: false}; + // extra keys + _keys['space'] = {code:32, shift: false}; + _keys['enter'] = {code:13, shift: false}; + _keys['shift'] = {code:16, shift: undefined}; + _keys['esc'] = {code:27, shift: false}; + _keys['backspace'] = {code:8, shift: false}; + _keys['tab'] = {code:9, shift: false}; + _keys['ctrl'] = {code:17, shift: false}; + _keys['alt'] = {code:18, shift: false}; + _keys['delete'] = {code:46, shift: false}; + _keys['pageup'] = {code:33, shift: false}; + _keys['pagedown'] = {code:34, shift: false}; + // symbols + _keys['='] = {code:187, shift: false}; + _keys['-'] = {code:189, shift: false}; + _keys[']'] = {code:221, shift: false}; + _keys['['] = {code:219, shift: false}; - this.controlNodes.positions = {}; - if (this.controlNodes.from.selected == false) { - this.controlNodes.positions.from = this.getControlNodeFromPosition(ctx); - this.controlNodes.from.x = this.controlNodes.positions.from.x; - this.controlNodes.from.y = this.controlNodes.positions.from.y; - } - if (this.controlNodes.to.selected == false) { - this.controlNodes.positions.to = this.getControlNodeToPosition(ctx); - this.controlNodes.to.x = this.controlNodes.positions.to.x; - this.controlNodes.to.y = this.controlNodes.positions.to.y; - } - this.controlNodes.from.draw(ctx); - this.controlNodes.to.draw(ctx); - } - else { - this.controlNodes = {from:null, to:null, positions:{}}; - } - }; - /** - * Enable control nodes. - * @private - */ - Edge.prototype._enableControlNodes = function() { - this.fromBackup = this.from; - this.toBackup = this.to; - this.controlNodesEnabled = true; - }; + var down = function(event) {handleEvent(event,'keydown');}; + var up = function(event) {handleEvent(event,'keyup');}; - /** - * disable control nodes and remove from dynamicEdges from old node - * @private - */ - Edge.prototype._disableControlNodes = function() { - this.fromId = this.from.id; - this.toId = this.to.id; - if (this.fromId != this.fromBackup.id) { // from was changed, remove edge from old 'from' node dynamic edges - this.fromBackup.detachEdge(this); - } - else if (this.toId != this.toBackup.id) { // to was changed, remove edge from old 'to' node dynamic edges - this.toBackup.detachEdge(this); - } + // handle the actualy bound key with the event + var handleEvent = function(event,type) { + if (_bound[type][event.keyCode] !== undefined) { + var bound = _bound[type][event.keyCode]; + for (var i = 0; i < bound.length; i++) { + if (bound[i].shift === undefined) { + bound[i].fn(event); + } + else if (bound[i].shift == true && event.shiftKey == true) { + bound[i].fn(event); + } + else if (bound[i].shift == false && event.shiftKey == false) { + bound[i].fn(event); + } + } - this.fromBackup = null; - this.toBackup = null; - this.controlNodesEnabled = false; - }; + if (preventDefault == true) { + event.preventDefault(); + } + } + }; + // bind a key to a callback + _exportFunctions.bind = function(key, callback, type) { + if (type === undefined) { + type = 'keydown'; + } + if (_keys[key] === undefined) { + throw new Error("unsupported key: " + key); + } + if (_bound[type][_keys[key].code] === undefined) { + _bound[type][_keys[key].code] = []; + } + _bound[type][_keys[key].code].push({fn:callback, shift:_keys[key].shift}); + }; - /** - * This checks if one of the control nodes is selected and if so, returns the control node object. Else it returns null. - * @param x - * @param y - * @returns {null} - * @private - */ - Edge.prototype._getSelectedControlNode = function(x,y) { - var positions = this.controlNodes.positions; - var fromDistance = Math.sqrt(Math.pow(x - positions.from.x,2) + Math.pow(y - positions.from.y,2)); - var toDistance = Math.sqrt(Math.pow(x - positions.to.x ,2) + Math.pow(y - positions.to.y ,2)); - 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; - } - }; + // bind all keys to a call back (demo purposes) + _exportFunctions.bindAll = function(callback, type) { + if (type === undefined) { + type = 'keydown'; + } + for (var key in _keys) { + if (_keys.hasOwnProperty(key)) { + _exportFunctions.bind(key,callback,type); + } + } + }; + // get the key label from an event + _exportFunctions.getKey = function(event) { + for (var key in _keys) { + if (_keys.hasOwnProperty(key)) { + if (event.shiftKey == true && _keys[key].shift == true && event.keyCode == _keys[key].code) { + return key; + } + else if (event.shiftKey == false && _keys[key].shift == false && event.keyCode == _keys[key].code) { + return key; + } + else if (event.keyCode == _keys[key].code && key == 'shift') { + return key; + } + } + } + return "unknown key, currently not supported"; + }; - /** - * 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(); - } - else if (this.controlNodes.to.selected == true) { - this.to = this.connectedNode; - this.connectedNode = null; - this.controlNodes.to.unselect(); - } - }; + // unbind either a specific callback from a key or all of them (by leaving callback undefined) + _exportFunctions.unbind = function(key, callback, type) { + if (type === undefined) { + type = 'keydown'; + } + if (_keys[key] === undefined) { + throw new Error("unsupported key: " + key); + } + if (callback !== undefined) { + var newBindings = []; + var bound = _bound[type][_keys[key].code]; + if (bound !== undefined) { + for (var i = 0; i < bound.length; i++) { + if (!(bound[i].fn == callback && bound[i].shift == _keys[key].shift)) { + newBindings.push(_bound[type][_keys[key].code][i]); + } + } + } + _bound[type][_keys[key].code] = newBindings; + } + else { + _bound[type][_keys[key].code] = []; + } + }; - /** - * this calculates the position of the control nodes on the edges of the parent nodes. - * - * @param ctx - * @returns {x: *, y: *} - */ - Edge.prototype.getControlNodeFromPosition = function(ctx) { - // draw arrow head - var controlnodeFromPos; - if (this.options.smoothCurves.enabled == true) { - controlnodeFromPos = this._findBorderPosition(true, ctx); - } - else { - 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); + // reset all bound variables. + _exportFunctions.reset = function() { + _bound = {keydown:{}, keyup:{}}; + }; - var fromBorderDist = this.from.distanceToBorder(ctx, angle + Math.PI); - var fromBorderPoint = (edgeSegmentLength - fromBorderDist) / edgeSegmentLength; - controlnodeFromPos = {}; - controlnodeFromPos.x = (fromBorderPoint) * this.from.x + (1 - fromBorderPoint) * this.to.x; - controlnodeFromPos.y = (fromBorderPoint) * this.from.y + (1 - fromBorderPoint) * this.to.y; - } + // unbind all listeners and reset all variables. + _exportFunctions.destroy = function() { + _bound = {keydown:{}, keyup:{}}; + container.removeEventListener('keydown', down, true); + container.removeEventListener('keyup', up, true); + }; - return controlnodeFromPos; - }; + // create listeners. + container.addEventListener('keydown',down,true); + container.addEventListener('keyup',up,true); - /** - * 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.getControlNodeToPosition = function(ctx) { - // draw arrow head - var controlnodeFromPos,controlnodeToPos; - if (this.options.smoothCurves.enabled == true) { - controlnodeToPos = this._findBorderPosition(false, ctx); + // return the public functions. + return _exportFunctions; } - else { - 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 toBorderDist = this.to.distanceToBorder(ctx, angle); - var toBorderPoint = (edgeSegmentLength - toBorderDist) / edgeSegmentLength; - controlnodeToPos = {}; - controlnodeToPos.x = (1 - toBorderPoint) * this.from.x + toBorderPoint * this.to.x; - controlnodeToPos.y = (1 - toBorderPoint) * this.from.y + toBorderPoint * this.to.y; - } + return keycharm; + })); + - return controlnodeToPos; - }; - module.exports = Edge; /***/ }, /* 38 */ /***/ function(module, exports, __webpack_require__) { var util = __webpack_require__(1); + var Component = __webpack_require__(23); + var TimeStep = __webpack_require__(27); + var DateUtil = __webpack_require__(24); + var moment = __webpack_require__(2); /** - * @class Groups - * This class can store groups and properties specific for groups. + * 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 Groups() { - this.clear(); - this.defaultIndex = 0; - this.groupsArray = []; - this.groupIndex = 0; - this.useDefaultGroups = true; - } - + function TimeAxis (body, options) { + this.dom = { + foreground: null, + lines: [], + majorTexts: [], + minorTexts: [], + redundant: { + lines: [], + majorTexts: [], + minorTexts: [] + } + }; + this.props = { + range: { + start: 0, + end: 0, + minimumStep: 0 + }, + lineTop: 0 + }; - /** - * default constants for group colors - */ - Groups.DEFAULT = [ - {border: "#2B7CE9", background: "#97C2FC", highlight: {border: "#2B7CE9", background: "#D2E5FF"}, hover: {border: "#2B7CE9", background: "#D2E5FF"}}, // 0: blue - {border: "#FFA500", background: "#FFFF00", highlight: {border: "#FFA500", background: "#FFFFA3"}, hover: {border: "#FFA500", background: "#FFFFA3"}}, // 1: yellow - {border: "#FA0A10", background: "#FB7E81", highlight: {border: "#FA0A10", background: "#FFAFB1"}, hover: {border: "#FA0A10", background: "#FFAFB1"}}, // 2: red - {border: "#41A906", background: "#7BE141", highlight: {border: "#41A906", background: "#A1EC76"}, hover: {border: "#41A906", background: "#A1EC76"}}, // 3: green - {border: "#E129F0", background: "#EB7DF4", highlight: {border: "#E129F0", background: "#F0B3F5"}, hover: {border: "#E129F0", background: "#F0B3F5"}}, // 4: magenta - {border: "#7C29F0", background: "#AD85E4", highlight: {border: "#7C29F0", background: "#D3BDF0"}, hover: {border: "#7C29F0", background: "#D3BDF0"}}, // 5: purple - {border: "#C37F00", background: "#FFA807", highlight: {border: "#C37F00", background: "#FFCA66"}, hover: {border: "#C37F00", background: "#FFCA66"}}, // 6: orange - {border: "#4220FB", background: "#6E6EFD", highlight: {border: "#4220FB", background: "#9B9BFD"}, hover: {border: "#4220FB", background: "#9B9BFD"}}, // 7: darkblue - {border: "#FD5A77", background: "#FFC0CB", highlight: {border: "#FD5A77", background: "#FFD1D9"}, hover: {border: "#FD5A77", background: "#FFD1D9"}}, // 8: pink - {border: "#4AD63A", background: "#C2FABC", highlight: {border: "#4AD63A", background: "#E6FFE3"}, hover: {border: "#4AD63A", background: "#E6FFE3"}}, // 9: mint + this.defaultOptions = { + orientation: 'bottom', // supported: 'top', 'bottom' + // TODO: implement timeaxis orientations 'left' and 'right' + showMinorLabels: true, + showMajorLabels: true, + format: null, + timeAxis: null + }; + this.options = util.extend({}, this.defaultOptions); - {border: "#990000", background: "#EE0000", highlight: {border: "#BB0000", background: "#FF3333"}, hover: {border: "#BB0000", background: "#FF3333"}}, // 10:bright red + this.body = body; - {border: "#FF6000", background: "#FF6000", highlight: {border: "#FF6000", background: "#FF6000"}, hover: {border: "#FF6000", background: "#FF6000"}}, // 12: real orange - {border: "#97C2FC", background: "#2B7CE9", highlight: {border: "#D2E5FF", background: "#2B7CE9"}, hover: {border: "#D2E5FF", background: "#2B7CE9"}}, // 13: blue - {border: "#399605", background: "#255C03", highlight: {border: "#399605", background: "#255C03"}, hover: {border: "#399605", background: "#255C03"}}, // 14: green - {border: "#B70054", background: "#FF007E", highlight: {border: "#B70054", background: "#FF007E"}, hover: {border: "#B70054", background: "#FF007E"}}, // 15: magenta - {border: "#AD85E4", background: "#7C29F0", highlight: {border: "#D3BDF0", background: "#7C29F0"}, hover: {border: "#D3BDF0", background: "#7C29F0"}}, // 16: purple - {border: "#4557FA", background: "#000EA1", highlight: {border: "#6E6EFD", background: "#000EA1"}, hover: {border: "#6E6EFD", background: "#000EA1"}}, // 17: darkblue - {border: "#FFC0CB", background: "#FD5A77", highlight: {border: "#FFD1D9", background: "#FD5A77"}, hover: {border: "#FFD1D9", background: "#FD5A77"}}, // 18: pink - {border: "#C2FABC", background: "#74D66A", highlight: {border: "#E6FFE3", background: "#74D66A"}, hover: {border: "#E6FFE3", background: "#74D66A"}}, // 19: mint + // create the HTML DOM + this._create(); - {border: "#EE0000", background: "#990000", highlight: {border: "#FF3333", background: "#BB0000"}, hover: {border: "#FF3333", background: "#BB0000"}}, // 20:bright red - ]; + this.setOptions(options); + } + TimeAxis.prototype = new Component(); /** - * Clear all groups + * Set options for the TimeAxis. + * Parameters will be merged in current options. + * @param {Object} options Available options: + * {string} [orientation] + * {boolean} [showMinorLabels] + * {boolean} [showMajorLabels] */ - Groups.prototype.clear = function () { - this.groups = {}; - this.groups.length = function() - { - var i = 0; - for ( var p in this ) { - if (this.hasOwnProperty(p)) { - i++; + TimeAxis.prototype.setOptions = function(options) { + if (options) { + // copy all options that we know + util.selectiveExtend([ + 'orientation', + 'showMinorLabels', + 'showMajorLabels', + 'hiddenDates', + 'format', + 'timeAxis' + ], this.options, options); + + // apply locale to moment.js + // TODO: not so nice, this is applied globally to moment.js + if ('locale' in options) { + if (typeof moment.locale === 'function') { + // moment.js 2.8.1+ + moment.locale(options.locale); + } + else { + moment.lang(options.locale); } } - return i; } }; - /** - * 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 + * Create the HTML DOM for the TimeAxis */ - Groups.prototype.get = function (groupname) { - var group = this.groups[groupname]; - if (group == undefined) { - if (this.useDefaultGroups === false && this.groupsArray.length > 0) { - // create new group - var index = this.groupIndex % this.groupsArray.length; - this.groupIndex++; - group = {}; - group.color = this.groups[this.groupsArray[index]]; - this.groups[groupname] = group; - } - else { - // create new group - var index = this.defaultIndex % Groups.DEFAULT.length; - this.defaultIndex++; - group = {}; - group.color = Groups.DEFAULT[index]; - this.groups[groupname] = group; - } - } + TimeAxis.prototype._create = function() { + this.dom.foreground = document.createElement('div'); + this.dom.background = document.createElement('div'); - return group; + this.dom.foreground.className = 'timeaxis foreground'; + this.dom.background.className = 'timeaxis background'; }; /** - * Add a custom group style - * @param {String} groupName - * @param {Object} style An object containing borderColor, - * backgroundColor, etc. - * @return {Object} group The created group object + * Destroy the TimeAxis */ - Groups.prototype.add = function (groupName, style) { - this.groups[groupName] = style; - this.groupsArray.push(groupName); - return style; - }; - - module.exports = Groups; - + TimeAxis.prototype.destroy = function() { + // remove from DOM + if (this.dom.foreground.parentNode) { + this.dom.foreground.parentNode.removeChild(this.dom.foreground); + } + if (this.dom.background.parentNode) { + this.dom.background.parentNode.removeChild(this.dom.background); + } -/***/ }, -/* 39 */ -/***/ function(module, exports, __webpack_require__) { + this.body = null; + }; /** - * @class Images - * This class loads images and keeps them stored. + * Repaint the component + * @return {boolean} Returns true if the component is resized */ - function Images() { - this.images = {}; - this.imageBroken = {}; - this.callback = undefined; - } + TimeAxis.prototype.redraw = function () { + var options = this.options; + var props = this.props; + var foreground = this.dom.foreground; + var background = this.dom.background; - /** - * 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; - }; + // 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); - /** - * - * @param {string} url Url of the image - * @param {string} url Url of an image to use if the url image is not found - * @return {Image} img The image object - */ - Images.prototype.load = function(url, brokenUrl) { - var img = this.images[url]; // make a pointer - if (img === undefined) { - // create the image - var me = this; - img = new Image(); - img.onload = function () { - // IE11 fix -- thanks dponch! - if (this.width == 0) { - document.body.appendChild(this); - this.width = this.offsetWidth; - this.height = this.offsetHeight; - document.body.removeChild(this); - } + // calculate character width and height + this._calculateCharSize(); - if (me.callback) { - me.images[url] = img; - me.callback(this); - } - }; + // 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; - img.onerror = function () { - if (brokenUrl === undefined) { - console.error("Could not load image:", url); - delete this.src; - if (me.callback) { - me.callback(this); - } - } - else { - if (me.imageBroken[url] === true) { - if (this.src == brokenUrl) { - console.error("Could not load brokenImage:", brokenUrl); - delete this.src; - if (me.callback) { - me.callback(this); - } - } - else { - console.error("Could not load image:", url); - this.src = brokenUrl; - } - } - else { - console.error("Could not load image:", url); - this.src = brokenUrl; - me.imageBroken[url] = true; - } - } - }; + // 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; - img.src = url; - } + 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 - return img; - }; + // 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); - module.exports = Images; + foreground.style.height = this.props.height + 'px'; + this._repaintLabels(); -/***/ }, -/* 40 */ -/***/ function(module, exports, __webpack_require__) { + // 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) + } - var util = __webpack_require__(1); + return this._isResized() || parentChanged; + }; /** - * @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", "icon" - * {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 - * + * Repaint major and minor text labels and vertical grid lines + * @private */ - function Node(properties, imagelist, grouplist, networkConstants) { - var constants = util.selectiveBridgeObject(['nodes'],networkConstants); - this.options = constants.nodes; - - this.selected = false; - this.hover = false; + TimeAxis.prototype._repaintLabels = function () { + var orientation = this.options.orientation; - this.edges = []; // all edges connected to this node - this.dynamicEdges = []; - this.reroutedEdges = {}; + // calculate range and step (step such that we have space for 7 characters per label) + var start = util.convert(this.body.range.start, 'Number'); + var end = util.convert(this.body.range.end, 'Number'); + var timeLabelsize = this.body.util.toTime((this.props.minorCharWidth || 10) * 7).valueOf(); + var minimumStep = timeLabelsize - DateUtil.getHiddenDurationBefore(this.body.hiddenDates, this.body.range, timeLabelsize); + minimumStep -= this.body.util.toTime(0).valueOf(); - // set defaults for the properties - this.id = undefined; - this.allowedToMoveX = false; - this.allowedToMoveY = false; - this.xFixed = false; - this.yFixed = false; - this.horizontalAlignLeft = true; // these are for the navigation controls - this.verticalAlignTop = true; // these are for the navigation controls - this.baseRadiusValue = networkConstants.nodes.radius; - this.radiusFixed = false; - this.level = -1; - this.preassignedLevel = false; - this.hierarchyEnumerated = false; - this.labelDimensions = {top:0, left:0, width:0, height:0, yLine:0}; // could be cached - this.boundingBox = {top:0, left:0, right:0, bottom:0}; + var step = new TimeStep(new Date(start), new Date(end), minimumStep, this.body.hiddenDates); + if (this.options.format) { + step.setFormat(this.options.format); + } + if (this.options.timeAxis) { + step.setScale(this.options.timeAxis); + } + this.step = step; - this.imagelist = imagelist; - this.grouplist = grouplist; + // 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.lines = dom.lines; + dom.redundant.majorTexts = dom.majorTexts; + dom.redundant.minorTexts = dom.minorTexts; + dom.lines = []; + dom.majorTexts = []; + dom.minorTexts = []; - // 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.x = null; - this.y = null; - this.predefinedPosition = false; // used to check if initial zoomExtent should just take the range or approximate + var cur; + var x = 0; + var isMajor; + var xPrev = 0; + var width = 0; + var prevLine; + var xFirstMajorLabel = undefined; + var max = 0; + var className; - // used for reverting to previous position on stabilization - this.previousState = {vx:0,vy:0,x:0,y:0}; + step.first(); + while (step.hasNext() && max < 1000) { + max++; - this.damping = networkConstants.physics.damping; // written every time gravity is calculated - this.fixedData = {x:null,y:null}; + cur = step.getCurrent(); + isMajor = step.isMajor(); + className = step.getClassName(); - this.setProperties(properties, constants); + xPrev = x; + x = this.body.util.toScreen(cur); + width = x - xPrev; + if (prevLine) { + prevLine.style.width = width + 'px'; + } - // creating the variables for clustering - this.resetCluster(); - this.clusterSession = 0; - this.clusterSizeWidthFactor = networkConstants.clustering.nodeScaling.width; - this.clusterSizeHeightFactor = networkConstants.clustering.nodeScaling.height; - this.clusterSizeRadiusFactor = networkConstants.clustering.nodeScaling.radius; - this.maxNodeSizeIncrements = networkConstants.clustering.maxNodeSizeIncrements; - this.growthIndicator = 0; + if (this.options.showMinorLabels) { + this._repaintMinorText(x, step.getLabelMinor(), orientation, className); + } - // 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 (isMajor && this.options.showMajorLabels) { + if (x > 0) { + if (xFirstMajorLabel == undefined) { + xFirstMajorLabel = x; + } + this._repaintMajorText(x, step.getLabelMajor(), orientation, className); + } + prevLine = this._repaintMajorLine(x, orientation, className); + } + else { + prevLine = this._repaintMinorLine(x, orientation, className); + } + step.next(); + } - /** - * Revert the position and velocity of the previous step. - */ - Node.prototype.revertPosition = function() { - this.x = this.previousState.x; - this.y = this.previousState.y; - this.vx = this.previousState.vx; - this.vy = this.previousState.vy; - } + // 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, className); + } + } - /** - * (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 = []; + // 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); + } + } + }); }; /** - * Attach a edge to the node - * @param {Edge} edge + * Create a minor label for the axis at position x + * @param {Number} x + * @param {String} text + * @param {String} orientation "top" or "bottom" (default) + * @param {String} className + * @private */ - 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); + TimeAxis.prototype._repaintMinorText = function (x, text, orientation, className) { + // 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); + 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.className = 'text minor ' + className; + //label.title = title; // TODO: this is a heavy operation }; /** - * Detach a edge from the node - * @param {Edge} edge + * Create a Major label for the axis at position x + * @param {Number} x + * @param {String} text + * @param {String} orientation "top" or "bottom" (default) + * @param {String} className + * @private */ - Node.prototype.detachEdge = function(edge) { - var index = this.edges.indexOf(edge); - if (index != -1) { - this.edges.splice(index, 1); - } - index = this.dynamicEdges.indexOf(edge); - if (index != -1) { - this.dynamicEdges.splice(index, 1); + TimeAxis.prototype._repaintMajorText = function (x, text, orientation, className) { + // reuse redundant label + var label = this.dom.redundant.majorTexts.shift(); + + if (!label) { + // create label + var content = document.createTextNode(text); + label = document.createElement('div'); + label.appendChild(content); + this.dom.foreground.appendChild(label); } - }; + this.dom.majorTexts.push(label); + label.childNodes[0].nodeValue = text; + label.className = 'text major ' + className; + //label.title = title; // TODO: this is a heavy operation - /** - * 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; - } - - var fields = ['borderWidth','borderWidthSelected','shape','image','brokenImage','radius','fontColor', - 'fontSize','fontFace','fontFill','fontStrokeWidth','fontStrokeColor','group','mass','fontDrawThreshold', - 'scaleFontWithValue','fontSizeMaxVisible','customScalingFunction','iconFontFace', 'icon', 'iconColor', 'iconSize' - ]; - util.selectiveDeepExtend(fields, this.options, properties); - - // basic properties - if (properties.id !== undefined) {this.id = properties.id;} - if (properties.label !== undefined) {this.label = properties.label; this.originalLabel = properties.label;} - if (properties.title !== undefined) {this.title = properties.title;} - if (properties.x !== undefined) {this.x = properties.x; this.predefinedPosition = true;} - if (properties.y !== undefined) {this.y = properties.y; this.predefinedPosition = true;} - if (properties.value !== undefined) {this.value = properties.value;} - if (properties.level !== undefined) {this.level = properties.level; this.preassignedLevel = true;} - - // 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;} + label.style.top = (orientation == 'top') ? '0' : (this.props.minorLabelHeight + 'px'); + label.style.left = x + 'px'; + }; - if (this.id === undefined) { - throw "Node must have an id"; + /** + * Create a minor line for the axis at position x + * @param {Number} x + * @param {String} orientation "top" or "bottom" (default) + * @param {String} className + * @return {Element} Returns the created line + * @private + */ + TimeAxis.prototype._repaintMinorLine = function (x, orientation, className) { + // reuse redundant line + var line = this.dom.redundant.lines.shift(); + if (!line) { + // create vertical line + line = document.createElement('div'); + this.dom.background.appendChild(line); } + this.dom.lines.push(line); - // copy group properties - if (typeof properties.group === 'number' || (typeof properties.group === 'string' && properties.group != '')) { - var groupObj = this.grouplist.get(properties.group); - util.deepExtend(this.options, groupObj); - // the color object needs to be completely defined. Since groups can partially overwrite the colors, we parse it again, just in case. - this.options.color = util.parseColor(this.options.color); + var props = this.props; + if (orientation == 'top') { + line.style.top = props.majorLabelHeight + 'px'; } - // individual shape properties - if (properties.radius !== undefined) {this.baseRadiusValue = this.options.radius;} - if (properties.color !== undefined) {this.options.color = util.parseColor(properties.color);} - - if (this.options.image !== undefined && this.options.image!= "") { - if (this.imagelist) { - this.imageObj = this.imagelist.load(this.options.image, this.options.brokenImage); - } - else { - throw "No imagelist provided"; - } + else { + line.style.top = this.body.domProps.top.height + 'px'; } + line.style.height = props.minorLineHeight + 'px'; + line.style.left = (x - props.minorLineWidth / 2) + 'px'; - if (properties.allowedToMoveX !== undefined) { - this.xFixed = !properties.allowedToMoveX; - this.allowedToMoveX = properties.allowedToMoveX; - } - else if (properties.x !== undefined && this.allowedToMoveX == false) { - this.xFixed = true; - } + line.className = 'grid vertical minor ' + className; + return line; + }; - if (properties.allowedToMoveY !== undefined) { - this.yFixed = !properties.allowedToMoveY; - this.allowedToMoveY = properties.allowedToMoveY; - } - else if (properties.y !== undefined && this.allowedToMoveY == false) { - this.yFixed = true; + /** + * Create a Major line for the axis at position x + * @param {Number} x + * @param {String} orientation "top" or "bottom" (default) + * @param {String} className + * @return {Element} Returns the created line + * @private + */ + TimeAxis.prototype._repaintMajorLine = function (x, orientation, className) { + // reuse redundant line + var line = this.dom.redundant.lines.shift(); + if (!line) { + // create vertical line + line = document.createElement('div'); + this.dom.background.appendChild(line); } + this.dom.lines.push(line); - this.radiusFixed = this.radiusFixed || (properties.radius !== undefined); - - if (this.options.shape === 'image' || this.options.shape === 'circularImage') { - this.options.radiusMin = constants.nodes.widthMin; - this.options.radiusMax = constants.nodes.widthMax; + var props = this.props; + if (orientation == 'top') { + line.style.top = '0'; } - - // choose draw method depending on the shape - switch (this.options.shape) { - case 'database': this.draw = this._drawDatabase; this.resize = this._resizeDatabase; break; - case 'box': this.draw = this._drawBox; this.resize = this._resizeBox; break; - case 'circle': this.draw = this._drawCircle; this.resize = this._resizeCircle; break; - case 'ellipse': this.draw = this._drawEllipse; this.resize = this._resizeEllipse; break; - // TODO: add diamond shape - case 'image': this.draw = this._drawImage; this.resize = this._resizeImage; break; - case 'circularImage': this.draw = this._drawCircularImage; this.resize = this._resizeCircularImage; 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; - case 'icon': this.draw = this._drawIcon; this.resize = this._resizeIcon; break; - default: this.draw = this._drawEllipse; this.resize = this._resizeEllipse; break; + else { + line.style.top = this.body.domProps.top.height + 'px'; } - // reset the size of the node, this can be changed - this._reset(); + line.style.left = (x - props.majorLineWidth / 2) + 'px'; + line.style.height = props.majorLineHeight + 'px'; - }; + line.className = 'grid vertical major ' + className; - /** - * select this node - */ - Node.prototype.select = function() { - this.selected = true; - this._reset(); + return line; }; /** - * unselect this node + * 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 */ - Node.prototype.unselect = function() { - this.selected = false; - this._reset(); - }; + 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'; - /** - * Reset the calculated size of the node, forces it to recalculate its size - */ - Node.prototype.clearSizeCache = function() { - this._reset(); - }; + 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; - /** - * Reset the calculated size of the node, forces it to recalculate its size - * @private - */ - Node.prototype._reset = function() { - this.width = undefined; - this.height = undefined; - }; + // 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 major measure'; + this.dom.measureCharMajor.style.position = 'absolute'; - /** - * 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; + 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; }; + module.exports = TimeAxis; + + +/***/ }, +/* 39 */ +/***/ function(module, exports, __webpack_require__) { + + var util = __webpack_require__(1); + var Component = __webpack_require__(23); + var moment = __webpack_require__(2); + var locales = __webpack_require__(40); + /** - * 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 + * A current time bar + * @param {{range: Range, dom: Object, domProps: Object}} body + * @param {Object} [options] Available parameters: + * {Boolean} [showCurrentTime] + * @constructor CurrentTime + * @extends Component */ - Node.prototype.distanceToBorder = function (ctx, angle) { - var borderWidth = 1; - - if (!this.width) { - this.resize(ctx); - } + function CurrentTime (body, options) { + this.body = body; - switch (this.options.shape) { - case 'circle': - case 'dot': - return this.options.radius+ borderWidth; + // default options + this.defaultOptions = { + showCurrentTime: true, - 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); + locales: locales, + locale: 'en' + }; + this.options = util.extend({}, this.defaultOptions); + this.offset = 0; - // TODO: implement distanceToBorder for database - // TODO: implement distanceToBorder for triangle - // TODO: implement distanceToBorder for triangleDown + this._create(); - 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.setOptions(options); + } - } - // TODO: implement calculation of distance to border for all shapes - }; + CurrentTime.prototype = new Component(); /** - * Set forces acting on the node - * @param {number} fx Force in horizontal direction - * @param {number} fy Force in vertical direction + * Create the HTML DOM for the current time bar + * @private */ - Node.prototype._setForce = function(fx, fy) { - this.fx = fx; - this.fy = fy; + 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; }; /** - * Add forces acting on the node - * @param {number} fx Force in horizontal direction - * @param {number} fy Force in vertical direction - * @private + * Destroy the CurrentTime bar */ - Node.prototype._addForce = function(fx, fy) { - this.fx += fx; - this.fy += fy; + CurrentTime.prototype.destroy = function () { + this.options.showCurrentTime = false; + this.redraw(); // will remove the bar from the DOM and stop refreshing + + this.body = null; }; /** - * Store the state before the next step + * Set options for the component. Options will be merged in current options. + * @param {Object} options Available parameters: + * {boolean} [showCurrentTime] */ - Node.prototype.storeState = function() { - this.previousState.x = this.x; - this.previousState.y = this.y; - this.previousState.vx = this.vx; - this.previousState.vy = this.vy; - } + CurrentTime.prototype.setOptions = function(options) { + if (options) { + // copy all options that we know + util.selectiveExtend(['showCurrentTime', 'locale', 'locales'], this.options, options); + } + }; /** - * Perform one discrete step for the node - * @param {number} interval Time interval in seconds + * Repaint the component + * @return {boolean} Returns true if the component is resized */ - Node.prototype.discreteStep = function(interval) { - this.storeState(); - if (!this.xFixed) { - var dx = this.damping * this.vx; // damping force - var ax = (this.fx - dx) / this.options.mass; // acceleration - this.vx += ax * interval; // velocity - this.x += this.vx * interval; // position - } - else { - this.fx = 0; - this.vx = 0; - } + 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); - if (!this.yFixed) { - var dy = this.damping * this.vy; // damping force - var ay = (this.fy - dy) / this.options.mass; // acceleration - this.vy += ay * interval; // velocity - this.y += this.vy * interval; // position - } - else { - this.fy = 0; - this.vy = 0; - } - }; + this.start(); + } + var now = new Date(new Date().valueOf() + this.offset); + var x = this.body.util.toScreen(now); + var locale = this.options.locales[this.options.locale]; + var title = locale.current + ' ' + locale.time + ': ' + moment(now).format('dddd, MMMM Do YYYY, H:mm:ss'); + title = title.charAt(0).toUpperCase() + title.substring(1); - /** - * 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) { - this.storeState(); - if (!this.xFixed) { - var dx = this.damping * this.vx; // damping force - var ax = (this.fx - dx) / this.options.mass; // acceleration - this.vx += ax * interval; // velocity - this.vx = (Math.abs(this.vx) > maxVelocity) ? ((this.vx > 0) ? maxVelocity : -maxVelocity) : this.vx; - this.x += this.vx * interval; // position + this.bar.style.left = x + 'px'; + this.bar.title = title; } else { - this.fx = 0; - this.vx = 0; + // remove the line from the DOM + if (this.bar.parentNode) { + this.bar.parentNode.removeChild(this.bar); + } + this.stop(); } - if (!this.yFixed) { - var dy = this.damping * this.vy; // damping force - var ay = (this.fy - dy) / this.options.mass; // acceleration - this.vy += ay * interval; // velocity - this.vy = (Math.abs(this.vy) > maxVelocity) ? ((this.vy > 0) ? maxVelocity : -maxVelocity) : this.vy; - this.y += this.vy * interval; // position - } - else { - this.fy = 0; - this.vy = 0; - } + return false; }; /** - * Check if this node has a fixed x and y position - * @return {boolean} true if fixed, false if not + * Start auto refreshing the current time bar */ - Node.prototype.isFixed = function() { - return (this.xFixed && this.yFixed); - }; + CurrentTime.prototype.start = function() { + var me = this; - /** - * 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 - */ - Node.prototype.isMoving = function(vmin) { - var velocity = Math.sqrt(Math.pow(this.vx,2) + Math.pow(this.vy,2)); - // this.velocity = Math.sqrt(Math.pow(this.vx,2) + Math.pow(this.vy,2)) - return (velocity > vmin); + 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(); }; /** - * check if this node is selecte - * @return {boolean} selected True if node is selected, else false + * Stop auto refreshing the current time bar */ - Node.prototype.isSelected = function() { - return this.selected; + CurrentTime.prototype.stop = function() { + if (this.currentTimeTimer !== undefined) { + clearTimeout(this.currentTimeTimer); + delete this.currentTimeTimer; + } }; /** - * Retrieve the value of the node. Can be undefined - * @return {Number} value + * Set a current time. This can be used for example to ensure that a client's + * time is synchronized with a shared server time. + * @param {Date | String | Number} time A Date, unix timestamp, or + * ISO date string. */ - Node.prototype.getValue = function() { - return this.value; + CurrentTime.prototype.setCurrentTime = function(time) { + var t = util.convert(time, 'Date').valueOf(); + var now = new Date().valueOf(); + this.offset = t - now; + this.redraw(); }; /** - * Calculate the distance from the nodes location to the given location (x,y) - * @param {Number} x - * @param {Number} y - * @return {Number} value + * Get the current time. + * @return {Date} Returns the current time. */ - Node.prototype.getDistance = function(x, y) { - var dx = this.x - x, - dy = this.y - y; - return Math.sqrt(dx * dx + dy * dy); + CurrentTime.prototype.getCurrentTime = function() { + return new Date(new Date().valueOf() + this.offset); }; + module.exports = CurrentTime; - /** - * 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, total) { - if (!this.radiusFixed && this.value !== undefined) { - var scale = this.options.customScalingFunction(min, max, total, this.value); - var radiusDiff = this.options.radiusMax - this.options.radiusMin; - if (this.options.scaleFontWithValue == true) { - var fontDiff = this.options.fontSizeMax - this.options.fontSizeMin; - this.options.fontSize = this.options.fontSizeMin + scale * fontDiff; - } - this.options.radius = this.options.radiusMin + scale * radiusDiff; - } - this.baseRadiusValue = this.options.radius; +/***/ }, +/* 40 */ +/***/ function(module, exports, __webpack_require__) { + + // English + exports['en'] = { + current: 'current', + time: 'time' }; + exports['en_EN'] = exports['en']; + exports['en_US'] = exports['en']; - /** - * 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"; + // Dutch + exports['nl'] = { + custom: 'aangepaste', + time: 'tijd' }; + exports['nl_NL'] = exports['nl']; + exports['nl_BE'] = exports['nl']; + + +/***/ }, +/* 41 */ +/***/ function(module, exports, __webpack_require__) { + + var Hammer = __webpack_require__(19); + var util = __webpack_require__(1); + var Component = __webpack_require__(23); + var moment = __webpack_require__(2); + var locales = __webpack_require__(40); /** - * 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 + * A custom time bar + * @param {{range: Range, dom: Object}} body + * @param {Object} [options] Available parameters: + * {Boolean} [showCustomTime] + * @constructor CustomTime + * @extends Component */ - Node.prototype.resize = function(ctx) { - throw "Resize method not initialized for node"; - }; - /** - * 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); - }; + function CustomTime (body, options) { + this.body = body; - Node.prototype._resizeImage = function (ctx) { - // TODO: pre calculate the image size + // default options + this.defaultOptions = { + showCustomTime: false, + locales: locales, + locale: 'en' + }; + this.options = util.extend({}, this.defaultOptions); - if (!this.width || !this.height) { // undefined or 0 - var width, height; - if (this.value) { - this.options.radius= this.baseRadiusValue; - var scale = this.imageObj.height / this.imageObj.width; - if (scale !== undefined) { - width = this.options.radius|| this.imageObj.width; - height = this.options.radius* scale || this.imageObj.height; - } - else { - width = 0; - height = 0; - } - } - else { - width = this.imageObj.width; - height = this.imageObj.height; - } - this.width = width; - this.height = height; + this.customTime = new Date(); + this.eventParams = {}; // stores state parameters while dragging the bar - this.growthIndicator = 0; - if (this.width > 0 && this.height > 0) { - this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeWidthFactor; - this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeHeightFactor; - this.options.radius+= Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeRadiusFactor; - this.growthIndicator = this.width - width; - } - } - }; + // create the DOM + this._create(); - Node.prototype._drawImageAtPosition = function (ctx) { - if (this.imageObj.width != 0 ) { - // draw the shade - if (this.clusterSize > 1) { - var lineWidth = ((this.clusterSize > 1) ? 10 : 0.0); - lineWidth *= this.networkScaleInv; - lineWidth = Math.min(0.2 * this.width,lineWidth); + this.setOptions(options); + } - ctx.globalAlpha = 0.5; - ctx.drawImage(this.imageObj, this.left - lineWidth, this.top - lineWidth, this.width + 2*lineWidth, this.height + 2*lineWidth); - } + CustomTime.prototype = new Component(); - // draw the image - ctx.globalAlpha = 1.0; - ctx.drawImage(this.imageObj, this.left, this.top, this.width, this.height); + /** + * 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', 'locale', 'locales'], this.options, options); } }; - Node.prototype._drawImageLabel = function (ctx) { - var yLabel; - var offset = 0; - - if (this.height){ - offset = this.height / 2; - var labelDimensions = this.getTextSize(ctx); - - if (labelDimensions.lineCount >= 1){ - offset += labelDimensions.height / 2; - offset += 3; - } - } - - yLabel = this.y + offset; + /** + * 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; - this._label(ctx, this.label, this.x, yLabel, undefined); - }; + 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); - Node.prototype._drawImage = function (ctx) { - this._resizeImage(ctx); - this.left = this.x - this.width / 2; - this.top = this.y - this.height / 2; + // 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)); + }; - this._drawImageAtPosition(ctx); + /** + * Destroy the CustomTime bar + */ + CustomTime.prototype.destroy = function () { + this.options.showCustomTime = false; + this.redraw(); // will remove the bar from the DOM - this.boundingBox.top = this.top; - this.boundingBox.left = this.left; - this.boundingBox.right = this.left + this.width; - this.boundingBox.bottom = this.top + this.height; + this.hammer.enable(false); + this.hammer = null; - this._drawImageLabel(ctx); - this.boundingBox.left = Math.min(this.boundingBox.left, this.labelDimensions.left); - this.boundingBox.right = Math.max(this.boundingBox.right, this.labelDimensions.left + this.labelDimensions.width); - this.boundingBox.bottom = Math.max(this.boundingBox.bottom, this.boundingBox.bottom + this.labelDimensions.height); + this.body = null; }; - Node.prototype._resizeCircularImage = function (ctx) { - if(!this.imageObj.src || !this.imageObj.width || !this.imageObj.height){ - if (!this.width) { - var diameter = this.options.radius * 2; - 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.options.radius += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeRadiusFactor; - this.growthIndicator = this.options.radius- 0.5*diameter; - this._swapToImageResizeWhenImageLoaded = true; + /** + * 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); + + var locale = this.options.locales[this.options.locale]; + var title = locale.time + ': ' + moment(this.customTime).format('dddd, MMMM Do YYYY, H:mm:ss'); + title = title.charAt(0).toUpperCase() + title.substring(1); + + this.bar.style.left = x + 'px'; + this.bar.title = title; } else { - if (this._swapToImageResizeWhenImageLoaded) { - this.width = 0; - this.height = 0; - delete this._swapToImageResizeWhenImageLoaded; + // remove the line from the DOM + if (this.bar.parentNode) { + this.bar.parentNode.removeChild(this.bar); } - this._resizeImage(ctx); } + return false; }; - Node.prototype._drawCircularImage = function (ctx) { - this._resizeCircularImage(ctx); + /** + * Set custom time. + * @param {Date | number | string} time + */ + CustomTime.prototype.setCustomTime = function(time) { + this.customTime = util.convert(time, 'Date'); + this.redraw(); + }; - this.left = this.x - this.width / 2; - this.top = this.y - this.height / 2; - - var centerX = this.left + (this.width / 2); - var centerY = this.top + (this.height / 2); - var radius = Math.abs(this.height / 2); + /** + * Retrieve the current custom time. + * @return {Date} customTime + */ + CustomTime.prototype.getCustomTime = function() { + return new Date(this.customTime.valueOf()); + }; - this._drawRawCircle(ctx, centerX, centerY, radius); + /** + * Start moving horizontally + * @param {Event} event + * @private + */ + CustomTime.prototype._onDragStart = function(event) { + this.eventParams.dragging = true; + this.eventParams.customTime = this.customTime; - ctx.save(); - ctx.circle(this.x, this.y, radius); - ctx.stroke(); - ctx.clip(); + event.stopPropagation(); + event.preventDefault(); + }; - this._drawImageAtPosition(ctx); + /** + * Perform moving operating. + * @param {Event} event + * @private + */ + CustomTime.prototype._onDrag = function (event) { + if (!this.eventParams.dragging) return; - ctx.restore(); + var deltaX = event.gesture.deltaX, + x = this.body.util.toScreen(this.eventParams.customTime) + deltaX, + time = this.body.util.toTime(x); - this.boundingBox.top = this.y - this.options.radius; - this.boundingBox.left = this.x - this.options.radius; - this.boundingBox.right = this.x + this.options.radius; - this.boundingBox.bottom = this.y + this.options.radius; + this.setCustomTime(time); - this._drawImageLabel(ctx); - - this.boundingBox.left = Math.min(this.boundingBox.left, this.labelDimensions.left); - this.boundingBox.right = Math.max(this.boundingBox.right, this.labelDimensions.left + this.labelDimensions.width); - this.boundingBox.bottom = Math.max(this.boundingBox.bottom, this.boundingBox.bottom + this.labelDimensions.height); + // fire a timechange event + this.body.emitter.emit('timechange', { + time: new Date(this.customTime.valueOf()) + }); + + event.stopPropagation(); + event.preventDefault(); }; - 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; + /** + * Stop moving operating. + * @param {event} event + * @private + */ + CustomTime.prototype._onDragEnd = function (event) { + if (!this.eventParams.dragging) return; - this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeWidthFactor; - this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeHeightFactor; - this.growthIndicator = this.width - (textSize.width + 2 * margin); - // this.options.radius+= Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeRadiusFactor; + // fire a timechanged event + this.body.emitter.emit('timechanged', { + time: new Date(this.customTime.valueOf()) + }); - } + event.stopPropagation(); + event.preventDefault(); }; - Node.prototype._drawBox = function (ctx) { - this._resizeBox(ctx); - - this.left = this.x - this.width / 2; - this.top = this.y - this.height / 2; + module.exports = CustomTime; - var clusterLineWidth = 2.5; - var borderWidth = this.options.borderWidth; - var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; - ctx.strokeStyle = this.selected ? this.options.color.highlight.border : this.hover ? this.options.color.hover.border : this.options.color.border; +/***/ }, +/* 42 */ +/***/ function(module, exports, __webpack_require__) { - // 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); + var Emitter = __webpack_require__(11); + var Hammer = __webpack_require__(19); + var util = __webpack_require__(1); + var DataSet = __webpack_require__(7); + var DataView = __webpack_require__(9); + var Range = __webpack_require__(21); + var Core = __webpack_require__(25); + var TimeAxis = __webpack_require__(38); + var CurrentTime = __webpack_require__(39); + var CustomTime = __webpack_require__(41); + var LineGraph = __webpack_require__(43); - ctx.roundRect(this.left-2*ctx.lineWidth, this.top-2*ctx.lineWidth, this.width+4*ctx.lineWidth, this.height+4*ctx.lineWidth, this.options.radius); - ctx.stroke(); + /** + * 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 + * @extends Core + */ + function Graph2d (container, items, groups, options) { + // if the third element is options, the forth is groups (optionally); + if (!(Array.isArray(groups) || groups instanceof DataSet) && groups instanceof Object) { + var forthArgument = options; + options = groups; + groups = forthArgument; } - ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); - ctx.lineWidth *= this.networkScaleInv; - ctx.lineWidth = Math.min(this.width,ctx.lineWidth); - ctx.fillStyle = this.selected ? this.options.color.highlight.background : this.hover ? this.options.color.hover.background : this.options.color.background; + var me = this; + this.defaultOptions = { + start: null, + end: null, - ctx.roundRect(this.left, this.top, this.width, this.height, this.options.radius); - ctx.fill(); - ctx.stroke(); + autoResize: true, - this.boundingBox.top = this.top; - this.boundingBox.left = this.left; - this.boundingBox.right = this.left + this.width; - this.boundingBox.bottom = this.top + this.height; + orientation: 'bottom', + width: null, + height: null, + maxHeight: null, + minHeight: null + }; + this.options = util.deepExtend({}, this.defaultOptions); - this._label(ctx, this.label, this.x, this.y); - }; + // Create the DOM, props, and emitter + this._create(container); + // all components listed here will be repainted automatically + this.components = []; - 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; + this.body = { + dom: this.dom, + domProps: this.props, + emitter: { + on: this.on.bind(this), + off: this.off.bind(this), + emit: this.emit.bind(this) + }, + hiddenDates: [], + util: { + 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) + } + }; - // scaling used for clustering - this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeWidthFactor; - this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeHeightFactor; - this.options.radius+= Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeRadiusFactor; - this.growthIndicator = this.width - size; - } - }; + // range + this.range = new Range(this.body); + this.components.push(this.range); + this.body.range = this.range; - Node.prototype._drawDatabase = function (ctx) { - this._resizeDatabase(ctx); - this.left = this.x - this.width / 2; - this.top = this.y - this.height / 2; + // time axis + this.timeAxis = new TimeAxis(this.body); + this.components.push(this.timeAxis); + //this.body.util.snap = this.timeAxis.snap.bind(this.timeAxis); - var clusterLineWidth = 2.5; - var borderWidth = this.options.borderWidth; - var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; + // current time bar + this.currentTime = new CurrentTime(this.body); + this.components.push(this.currentTime); - ctx.strokeStyle = this.selected ? this.options.color.highlight.border : this.hover ? this.options.color.hover.border : this.options.color.border; + // 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); - // 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); + // item set + this.linegraph = new LineGraph(this.body); + this.components.push(this.linegraph); - 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(); + this.itemsData = null; // DataSet + this.groupsData = null; // DataSet + + // apply options + if (options) { + this.setOptions(options); } - ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); - ctx.lineWidth *= this.networkScaleInv; - ctx.lineWidth = Math.min(this.width,ctx.lineWidth); - ctx.fillStyle = this.selected ? this.options.color.highlight.background : this.hover ? this.options.color.hover.background : this.options.color.background; - ctx.database(this.x - this.width/2, this.y - this.height*0.5, this.width, this.height); - ctx.fill(); - ctx.stroke(); + // IMPORTANT: THIS HAPPENS BEFORE SET ITEMS! + if (groups) { + this.setGroups(groups); + } - this.boundingBox.top = this.top; - this.boundingBox.left = this.left; - this.boundingBox.right = this.left + this.width; - this.boundingBox.bottom = this.top + this.height; + // create itemset + if (items) { + this.setItems(items); + } + else { + this._redraw(); + } + } - this._label(ctx, this.label, this.x, this.y); - }; + // Extend the functionality from Core + Graph2d.prototype = new Core(); + /** + * Set items + * @param {vis.DataSet | Array | google.visualization.DataTable | null} items + */ + Graph2d.prototype.setItems = function(items) { + var initialLoad = (this.itemsData == null); - Node.prototype._resizeCircle = function (ctx) { - if (!this.width) { - var margin = 5; - var textSize = this.getTextSize(ctx); - var diameter = Math.max(textSize.width, textSize.height) + 2 * margin; - this.options.radius = diameter / 2; + // 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' + } + }); + } - this.width = diameter; - this.height = diameter; + // set items + this.itemsData = newDataSet; + this.linegraph && this.linegraph.setItems(newDataSet); - // scaling used for clustering - // this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeWidthFactor; - // this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeHeightFactor; - this.options.radius += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeRadiusFactor; - this.growthIndicator = this.options.radius- 0.5*diameter; + if (initialLoad) { + if (this.options.start != undefined || this.options.end != undefined) { + var start = this.options.start != undefined ? this.options.start : null; + var end = this.options.end != undefined ? this.options.end : null; + + this.setWindow(start, end, {animate: false}); + } + else { + this.fit({animate: false}); + } } }; - Node.prototype._drawRawCircle = function (ctx, x, y, radius) { - var clusterLineWidth = 2.5; - var borderWidth = this.options.borderWidth; - var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; - - ctx.strokeStyle = this.selected ? this.options.color.highlight.border : this.hover ? this.options.color.hover.border : this.options.color.border; - - // draw the outer border - if (this.clusterSize > 1) { - ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); - ctx.lineWidth *= this.networkScaleInv; - ctx.lineWidth = Math.min(this.width,ctx.lineWidth); - - ctx.circle(x, y, radius+2*ctx.lineWidth); - ctx.stroke(); + /** + * Set groups + * @param {vis.DataSet | Array | google.visualization.DataTable} groups + */ + Graph2d.prototype.setGroups = function(groups) { + // convert to type DataSet when needed + var newDataSet; + if (!groups) { + newDataSet = null; + } + else if (groups instanceof DataSet || groups instanceof DataView) { + newDataSet = groups; + } + else { + // turn an array into a dataset + newDataSet = new DataSet(groups); } - ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); - ctx.lineWidth *= this.networkScaleInv; - ctx.lineWidth = Math.min(this.width,ctx.lineWidth); - ctx.fillStyle = this.selected ? this.options.color.highlight.background : this.hover ? this.options.color.hover.background : this.options.color.background; - ctx.circle(this.x, this.y, radius); - ctx.fill(); - ctx.stroke(); + this.groupsData = newDataSet; + this.linegraph.setGroups(newDataSet); }; - Node.prototype._drawCircle = function (ctx) { - this._resizeCircle(ctx); - this.left = this.x - this.width / 2; - this.top = this.y - this.height / 2; + /** + * Returns an object containing an SVG element with the icon of the group (size determined by iconWidth and iconHeight), the label of the group (content) and the yAxisOrientation of the group (left or right). + * @param groupId + * @param width + * @param height + */ + Graph2d.prototype.getLegend = function(groupId, width, height) { + if (width === undefined) {width = 15;} + if (height === undefined) {height = 15;} + if (this.linegraph.groups[groupId] !== undefined) { + return this.linegraph.groups[groupId].getLegend(width,height); + } + else { + return "cannot find group:" + groupId; + } + } - this._drawRawCircle(ctx, this.x, this.y, this.options.radius); + /** + * This checks if the visible option of the supplied group (by ID) is true or false. + * @param groupId + * @returns {*} + */ + Graph2d.prototype.isGroupVisible = function(groupId) { + if (this.linegraph.groups[groupId] !== undefined) { + return (this.linegraph.groups[groupId].visible && (this.linegraph.options.groups.visibility[groupId] === undefined || this.linegraph.options.groups.visibility[groupId] == true)); + } + else { + return false; + } + } - this.boundingBox.top = this.y - this.options.radius; - this.boundingBox.left = this.x - this.options.radius; - this.boundingBox.right = this.x + this.options.radius; - this.boundingBox.bottom = this.y + this.options.radius; - this._label(ctx, this.label, this.x, this.y); - }; - - Node.prototype._resizeEllipse = function (ctx) { - if (!this.width) { - var textSize = this.getTextSize(ctx); + /** + * Get the data range of the item set. + * @returns {{min: Date, max: Date}} range A range with a start and end Date. + * When no minimum is found, min==null + * When no maximum is found, max==null + */ + Graph2d.prototype.getItemRange = function() { + var min = null; + var max = null; - this.width = textSize.width * 1.5; - this.height = textSize.height * 2; - if (this.width < this.height) { - this.width = this.height; + // calculate min from start filed + for (var groupId in this.linegraph.groups) { + if (this.linegraph.groups.hasOwnProperty(groupId)) { + if (this.linegraph.groups[groupId].visible == true) { + for (var i = 0; i < this.linegraph.groups[groupId].itemsData.length; i++) { + var item = this.linegraph.groups[groupId].itemsData[i]; + var value = util.convert(item.x, 'Date').valueOf(); + min = min == null ? value : min > value ? value : min; + max = max == null ? value : max < value ? value : max; + } + } } - 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.options.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; + return { + min: (min != null) ? new Date(min) : null, + max: (max != null) ? new Date(max) : null + }; + }; - var clusterLineWidth = 2.5; - var borderWidth = this.options.borderWidth; - var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; - ctx.strokeStyle = this.selected ? this.options.color.highlight.border : this.hover ? this.options.color.hover.border : this.options.color.border; - // draw the outer border - if (this.clusterSize > 1) { - ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); - ctx.lineWidth *= this.networkScaleInv; - ctx.lineWidth = Math.min(this.width,ctx.lineWidth); + module.exports = Graph2d; - 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); - ctx.fillStyle = this.selected ? this.options.color.highlight.background : this.hover ? this.options.color.hover.background : this.options.color.background; +/***/ }, +/* 43 */ +/***/ function(module, exports, __webpack_require__) { - ctx.ellipse(this.left, this.top, this.width, this.height); - ctx.fill(); - ctx.stroke(); + var util = __webpack_require__(1); + var DOMutil = __webpack_require__(6); + var DataSet = __webpack_require__(7); + var DataView = __webpack_require__(9); + var Component = __webpack_require__(23); + var DataAxis = __webpack_require__(44); + var GraphGroup = __webpack_require__(46); + var Legend = __webpack_require__(50); + var BarGraphFunctions = __webpack_require__(49); - this.boundingBox.top = this.top; - this.boundingBox.left = this.left; - this.boundingBox.right = this.left + this.width; - this.boundingBox.bottom = this.top + this.height; + var UNGROUPED = '__ungrouped__'; // reserved group id for ungrouped items - this._label(ctx, this.label, this.x, this.y); - }; + /** + * This is the constructor of the LineGraph. It requires a Timeline body and options. + * + * @param body + * @param options + * @constructor + */ + function LineGraph(body, options) { + this.id = util.randomUUID(); + this.body = body; - Node.prototype._drawDot = function (ctx) { - this._drawShape(ctx, 'circle'); - }; + 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, + handleOverlap: 'overlap', + 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, + alignZeros: true, + customRange: { + left: {min:undefined, max:undefined}, + right: {min:undefined, max:undefined} + } + //, these options are not set by default, but this shows the format they will be in + //format: { + // left: {decimals: 2}, + // right: {decimals: 2} + //}, + //title: { + // left: { + // text: 'left', + // style: 'color:black;' + // }, + // right: { + // text: 'right', + // style: 'color:black;' + // } + //} + }, + 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 + } + }, + groups: { + visibility: {} + } + }; - Node.prototype._drawTriangle = function (ctx) { - this._drawShape(ctx, 'triangle'); - }; + // options is shared by this ItemSet and all its items + this.options = util.extend({}, this.defaultOptions); + this.dom = {}; + this.props = {}; + this.hammer = null; + this.groups = {}; + this.abortedGraphUpdate = false; + this.updateSVGheight = false; + this.updateSVGheightOnResize = false; - Node.prototype._drawTriangleDown = function (ctx) { - this._drawShape(ctx, 'triangleDown'); - }; + var me = this; + this.itemsData = null; // DataSet + this.groupsData = null; // DataSet - Node.prototype._drawSquare = function (ctx) { - this._drawShape(ctx, 'square'); - }; + // 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); + } + }; - Node.prototype._drawStar = function (ctx) { - this._drawShape(ctx, 'star'); - }; + // 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); + } + }; - Node.prototype._resizeShape = function (ctx) { - if (!this.width) { - this.options.radius= this.baseRadiusValue; - var size = 2 * this.options.radius; - this.width = size; - this.height = size; + 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 - // scaling used for clustering - this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeWidthFactor; - this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeHeightFactor; - this.options.radius+= Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeRadiusFactor; - this.growthIndicator = this.width - size; - } - }; + this.svgElements = {}; + this.setOptions(options); + this.groupsUsingDefaultStyles = [0]; + this.COUNTER = 0; + this.body.emitter.on('rangechanged', function() { + me.lastStart = me.body.range.start; + me.svg.style.left = util.option.asSize(-me.props.width); + me.redraw.call(me,true); + }); - Node.prototype._drawShape = function (ctx, shape) { - this._resizeShape(ctx); + // create the HTML DOM + this._create(); + this.framework = {svg: this.svg, svgElements: this.svgElements, options: this.options, groups: this.groups}; + this.body.emitter.emit('change'); - this.left = this.x - this.width / 2; - this.top = this.y - this.height / 2; + } - var clusterLineWidth = 2.5; - var borderWidth = this.options.borderWidth; - var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; - var radiusMultiplier = 2; + LineGraph.prototype = new Component(); - // 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; - } + /** + * Create the HTML DOM for the ItemSet + */ + LineGraph.prototype._create = function(){ + var frame = document.createElement('div'); + frame.className = 'LineGraph'; + this.dom.frame = frame; - ctx.strokeStyle = this.selected ? this.options.color.highlight.border : this.hover ? this.options.color.hover.border : this.options.color.border; - // draw the outer border - if (this.clusterSize > 1) { - ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); - ctx.lineWidth *= this.networkScaleInv; - ctx.lineWidth = Math.min(this.width,ctx.lineWidth); + // 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); - ctx[shape](this.x, this.y, this.options.radius+ radiusMultiplier * ctx.lineWidth); - ctx.stroke(); - } - ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); - ctx.lineWidth *= this.networkScaleInv; - ctx.lineWidth = Math.min(this.width,ctx.lineWidth); + // data axis + this.options.dataAxis.orientation = 'left'; + this.yAxisLeft = new DataAxis(this.body, this.options.dataAxis, this.svg, this.options.groups); - ctx.fillStyle = this.selected ? this.options.color.highlight.background : this.hover ? this.options.color.hover.background : this.options.color.background; - ctx[shape](this.x, this.y, this.options.radius); - ctx.fill(); - ctx.stroke(); + this.options.dataAxis.orientation = 'right'; + this.yAxisRight = new DataAxis(this.body, this.options.dataAxis, this.svg, this.options.groups); + delete this.options.dataAxis.orientation; - this.boundingBox.top = this.y - this.options.radius; - this.boundingBox.left = this.x - this.options.radius; - this.boundingBox.right = this.x + this.options.radius; - this.boundingBox.bottom = this.y + this.options.radius; + // legends + this.legendLeft = new Legend(this.body, this.options.legend, 'left', this.options.groups); + this.legendRight = new Legend(this.body, this.options.legend, 'right', this.options.groups); - if (this.label) { - this._label(ctx, this.label, this.x, this.y + this.height / 2, undefined, 'hanging',true); - this.boundingBox.left = Math.min(this.boundingBox.left, this.labelDimensions.left); - this.boundingBox.right = Math.max(this.boundingBox.right, this.labelDimensions.left + this.labelDimensions.width); - this.boundingBox.bottom = Math.max(this.boundingBox.bottom, this.boundingBox.bottom + this.labelDimensions.height); - } + this.show(); }; - 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; + /** + * set the options of the LineGraph. the mergeOptions is used for subObjects that have an enabled element. + * @param {object} options + */ + LineGraph.prototype.setOptions = function(options) { + if (options) { + var fields = ['sampling','defaultGroup','height','graphHeight','yAxisOrientation','style','barChart','dataAxis','sort','groups']; + if (options.graphHeight === undefined && options.height !== undefined && this.body.domProps.centerContainer.height !== undefined) { + this.updateSVGheight = true; + this.updateSVGheightOnResize = true; + } + else if (this.body.domProps.centerContainer.height !== undefined && options.graphHeight !== undefined) { + if (parseInt((options.graphHeight + '').replace("px",'')) < this.body.domProps.centerContainer.height) { + this.updateSVGheight = true; + } + } + 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'); - // scaling used for clustering - this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeWidthFactor; - this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeHeightFactor; - this.options.radius+= Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeRadiusFactor; - this.growthIndicator = this.width - (textSize.width + 2 * margin); - } - }; + 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; + } + } + } + } - Node.prototype._drawText = function (ctx) { - this._resizeText(ctx); - this.left = this.x - this.width / 2; - this.top = this.y - this.height / 2; + if (this.yAxisLeft) { + if (options.dataAxis !== undefined) { + this.yAxisLeft.setOptions(this.options.dataAxis); + this.yAxisRight.setOptions(this.options.dataAxis); + } + } - this._label(ctx, this.label, this.x, this.y); + if (this.legendLeft) { + if (options.legend !== undefined) { + this.legendLeft.setOptions(this.options.legend); + this.legendRight.setOptions(this.options.legend); + } + } - this.boundingBox.top = this.top; - this.boundingBox.left = this.left; - this.boundingBox.right = this.left + this.width; - this.boundingBox.bottom = this.top + this.height; + if (this.groups.hasOwnProperty(UNGROUPED)) { + this.groups[UNGROUPED].setOptions(options); + } + } + + // this is used to redraw the graph if the visibility of the groups is changed. + if (this.dom.frame) { + this.redraw(true); + } + }; + + /** + * Hide the component from the DOM + */ + LineGraph.prototype.hide = function() { + // remove the frame containing the items + if (this.dom.frame.parentNode) { + this.dom.frame.parentNode.removeChild(this.dom.frame); + } }; - Node.prototype._resizeIcon = function (ctx) { - if (!this.width) { - var margin = 5; - var iconSize = - { - width: Number(this.options.iconSize), - height: Number(this.options.iconSize) - }; - this.width = iconSize.width + 2 * margin; - this.height = iconSize.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.options.radius += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeRadiusFactor; - this.growthIndicator = this.width - (iconSize.width + 2 * margin); + /** + * 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); } }; - Node.prototype._drawIcon = function (ctx) { - this._resizeIcon(ctx); - this.options.iconSize = this.options.iconSize || 50; + /** + * Set items + * @param {vis.DataSet | null} items + */ + LineGraph.prototype.setItems = function(items) { + var me = this, + ids, + oldItemsData = this.itemsData; - this.left = this.x - this.width / 2; - this.top = this.y - this.height / 2; - this._icon(ctx); + // 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); + }); - this.boundingBox.top = this.y - this.options.iconSize/2; - this.boundingBox.left = this.x - this.options.iconSize/2; - this.boundingBox.right = this.x + this.options.iconSize/2; - this.boundingBox.bottom = this.y + this.options.iconSize/2; + // remove all drawn items + ids = oldItemsData.getIds(); + this._onRemove(ids); + } - if (this.label) { - var iconTextSpacing = 5; - this._label(ctx, this.label, this.x, this.y + this.height / 2 + iconTextSpacing, 'top', true); + if (this.itemsData) { + // subscribe to new dataset + var id = this.id; + util.forEach(this.itemListeners, function (callback, event) { + me.itemsData.on(event, callback, id); + }); - this.boundingBox.left = Math.min(this.boundingBox.left, this.labelDimensions.left); - this.boundingBox.right = Math.max(this.boundingBox.right, this.labelDimensions.left + this.labelDimensions.width); - this.boundingBox.bottom = Math.max(this.boundingBox.bottom, this.boundingBox.bottom + this.labelDimensions.height); + // add all new items + ids = this.itemsData.getIds(); + this._onAdd(ids); } + this._updateUngrouped(); + //this._updateGraph(); + this.redraw(true); }; - Node.prototype._icon = function (ctx) { - var relativeIconSize = Number(this.options.iconSize) * this.networkScale; - - if (this.options.icon && relativeIconSize > this.options.fontDrawThreshold - 1) { - var iconSize = Number(this.options.iconSize); + /** + * Set groups + * @param {vis.DataSet} groups + */ + LineGraph.prototype.setGroups = function(groups) { + var me = this; + var ids; - ctx.font = (this.selected ? "bold " : "") + iconSize + "px " + this.options.iconFontFace; + // unsubscribe from current dataset + if (this.groupsData) { + util.forEach(this.groupListeners, function (callback, event) { + me.groupsData.unsubscribe(event, callback); + }); - // draw icon - ctx.fillStyle = this.options.iconColor || "black"; - ctx.textAlign = "center"; - ctx.textBaseline = "middle"; - ctx.fillText(this.options.icon, this.x, this.y); + // remove all drawn groups + ids = this.groupsData.getIds(); + this.groupsData = null; + this._onRemoveGroups(ids); // note: this will cause a redraw } - }; - - Node.prototype._label = function (ctx, text, x, y, align, baseline, labelUnderNode) { - var relativeFontSize = Number(this.options.fontSize) * this.networkScale; - if (text && relativeFontSize >= this.options.fontDrawThreshold - 1) { - var fontSize = Number(this.options.fontSize); - - // this ensures that there will not be HUGE letters on screen by setting an upper limit on the visible text size (regardless of zoomLevel) - if (relativeFontSize >= this.options.fontSizeMaxVisible) { - fontSize = Number(this.options.fontSizeMaxVisible) * this.networkScaleInv; - } - // fade in when relative scale is between threshold and threshold - 1 - var fontColor = this.options.fontColor || "#000000"; - var strokecolor = this.options.fontStrokeColor; - if (relativeFontSize <= this.options.fontDrawThreshold) { - var opacity = Math.max(0,Math.min(1,1 - (this.options.fontDrawThreshold - relativeFontSize))); - fontColor = util.overrideOpacity(fontColor, opacity); - strokecolor = util.overrideOpacity(strokecolor, opacity); + // 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'); + } - } + if (this.groupsData) { + // subscribe to new dataset + var id = this.id; + util.forEach(this.groupListeners, function (callback, event) { + me.groupsData.on(event, callback, id); + }); - ctx.font = (this.selected ? "bold " : "") + fontSize + "px " + this.options.fontFace; + // draw all ms + ids = this.groupsData.getIds(); + this._onAddGroups(ids); + } + this._onUpdate(); + }; - var lines = text.split('\n'); - var lineCount = lines.length; - var yLine = y + (1 - lineCount) / 2 * fontSize; - if (labelUnderNode == true) { - yLine = y + (1 - lineCount) / (2 * fontSize); - } - // font fill from edges now for nodes! - var width = ctx.measureText(lines[0]).width; - for (var i = 1; i < lineCount; i++) { - var lineWidth = ctx.measureText(lines[i]).width; - width = lineWidth > width ? lineWidth : width; - } - var height = fontSize * lineCount; - var left = x - width / 2; - var top = y - height / 2; - if (baseline == "hanging") { - top += 0.5 * fontSize; - top += 4; // distance from node, required because we use hanging. Hanging has less difference between browsers - yLine += 4; // distance from node - } - this.labelDimensions = {top:top,left:left,width:width,height:height,yLine:yLine}; + /** + * Update the data + * @param [ids] + * @private + */ + LineGraph.prototype._onUpdate = function(ids) { + this._updateUngrouped(); + this._updateAllGroupData(); + //this._updateGraph(); + this.redraw(true); + }; + 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]); + } - // create the fontfill background - if (this.options.fontFill !== undefined && this.options.fontFill !== null && this.options.fontFill !== "none") { - ctx.fillStyle = this.options.fontFill; - ctx.fillRect(left, top, width, height); - } + //this._updateGraph(); + this.redraw(true); + }; + LineGraph.prototype._onAddGroups = function (groupIds) {this._onUpdateGroups(groupIds);}; - // draw text - ctx.fillStyle = fontColor; - ctx.textAlign = align || "center"; - ctx.textBaseline = baseline || "middle"; - if (this.options.fontStrokeWidth > 0){ - ctx.lineWidth = this.options.fontStrokeWidth; - ctx.strokeStyle = strokecolor; - ctx.lineJoin = 'round'; - } - for (var i = 0; i < lineCount; i++) { - if(this.options.fontStrokeWidth){ - ctx.strokeText(lines[i], x, yLine); + + /** + * this cleans the group out off the legends and the dataaxis, updates the ungrouped and updates the graph + * @param {Array} groupIds + * @private + */ + 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(); } - ctx.fillText(lines[i], x, yLine); - yLine += fontSize; + 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(true); }; - Node.prototype.getTextSize = function(ctx) { - if (this.label !== undefined) { - var fontSize = Number(this.options.fontSize); - if (fontSize * this.networkScale > this.options.fontSizeMaxVisible) { - fontSize = Number(this.options.fontSizeMaxVisible) * this.networkScaleInv; + /** + * update a group object with the group dataset entree + * + * @param group + * @param groupId + * @private + */ + LineGraph.prototype._updateGroup = function (group, groupId) { + if (!this.groups.hasOwnProperty(groupId)) { + this.groups[groupId] = new GraphGroup(group, groupId, this.options, this.groupsUsingDefaultStyles); + if (this.groups[groupId].options.yAxisOrientation == 'right') { + this.yAxisRight.addGroup(groupId, this.groups[groupId]); + this.legendRight.addGroup(groupId, this.groups[groupId]); } - ctx.font = (this.selected ? "bold " : "") + fontSize + "px " + this.options.fontFace; - - var lines = this.label.split('\n'), - height = (fontSize + 4) * lines.length, - width = 0; - - for (var i = 0, iMax = lines.length; i < iMax; i++) { - width = Math.max(width, ctx.measureText(lines[i]).width); + else { + this.yAxisLeft.addGroup(groupId, this.groups[groupId]); + this.legendLeft.addGroup(groupId, this.groups[groupId]); } - - return {"width": width, "height": height, lineCount: lines.length}; } else { - return {"width": 0, "height": 0, lineCount: 0}; + 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(); }; + /** - * 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; + * this updates all groups, it is used when there is an update the the itemset. * - * @returns {boolean} + * @private */ - 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; + LineGraph.prototype._updateAllGroupData = function () { + if (this.itemsData != null) { + var groupsContent = {}; + var groupId; + for (groupId in this.groups) { + if (this.groups.hasOwnProperty(groupId)) { + groupsContent[groupId] = []; + } + } + for (var itemId in this.itemsData._data) { + if (this.itemsData._data.hasOwnProperty(itemId)) { + var item = this.itemsData._data[itemId]; + if (groupsContent[item.group] === undefined) { + throw new Error('Cannot find referenced group. Possible reason: items added before groups? Groups need to be added before items, as items refer to groups.') + } + item.x = util.convert(item.x,'Date'); + groupsContent[item.group].push(item); + } + } + for (groupId in this.groups) { + if (this.groups.hasOwnProperty(groupId)) { + this.groups[groupId].setItems(groupsContent[groupId]); + } + } } }; - /** - * 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); - }; /** - * 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 + * 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 */ - Node.prototype.setScaleAndPos = function(scale,canvasTopLeft,canvasBottomRight) { - this.networkScaleInv = 1.0/scale; - this.networkScale = scale; - this.canvasTopLeft = canvasTopLeft; - this.canvasBottomRight = canvasBottomRight; - }; + LineGraph.prototype._updateUngrouped = function() { + if (this.itemsData && this.itemsData != null) { + var ungroupedCounter = 0; + 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; + } + } + } + if (ungroupedCounter == 0) { + delete this.groups[UNGROUPED]; + this.legendLeft.removeGroup(UNGROUPED); + this.legendRight.removeGroup(UNGROUPED); + this.yAxisLeft.removeGroup(UNGROUPED); + this.yAxisRight.removeGroup(UNGROUPED); + } + else { + var group = {id: UNGROUPED, content: this.options.defaultGroup}; + this._updateGroup(group, UNGROUPED); + } + } + else { + delete this.groups[UNGROUPED]; + this.legendLeft.removeGroup(UNGROUPED); + this.legendRight.removeGroup(UNGROUPED); + this.yAxisLeft.removeGroup(UNGROUPED); + this.yAxisRight.removeGroup(UNGROUPED); + } - /** - * 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; + this.legendLeft.redraw(); + this.legendRight.redraw(); }; - /** - * set the velocity at 0. Is called when this node is contained in another during clustering + * Redraw the component, mandatory function + * @return {boolean} Returns true if the component is resized */ - Node.prototype.clearVelocity = function() { - this.vx = 0; - this.vy = 0; - }; + LineGraph.prototype.redraw = function(forceGraphUpdate) { + var resized = false; + // calculate actual size and position + this.props.width = this.dom.frame.offsetWidth; + this.props.height = this.body.domProps.centerContainer.height; - /** - * 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.options.mass) : Math.sqrt(energyBefore/this.options.mass); - this.vx = Math.sqrt(energyBefore/this.options.mass); - energyBefore = this.vy * this.vy * massBeforeClustering; - //this.vy = (this.vy < 0) ? -Math.sqrt(energyBefore/this.options.mass) : Math.sqrt(energyBefore/this.options.mass); - this.vy = Math.sqrt(energyBefore/this.options.mass); - }; + // update the graph if there is no lastWidth or with, used for the initial draw + if (this.lastWidth === undefined && this.props.width) { + forceGraphUpdate = true; + } - module.exports = Node; + // 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.lastVisibleInterval = visibleInterval; -/***/ }, -/* 41 */ -/***/ function(module, exports, __webpack_require__) { - /** - * 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; - } + // 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.props.width); + this.svg.style.left = util.option.asSize(-this.props.width); - // 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' - } - } + // if the height of the graph is set as proportional, change the height of the svg + if ((this.options.height + '').indexOf("%") != -1 || this.updateSVGheightOnResize == true) { + this.updateSVGheight = true; } } - this.x = 0; - this.y = 0; - this.padding = 5; - this.hidden = false; - - if (x !== undefined && y !== undefined) { - this.setPosition(x, y); + // update the height of the graph on each redraw of the graph. + if (this.updateSVGheight == true) { + if (this.options.graphHeight != this.body.domProps.centerContainer.height + 'px') { + this.options.graphHeight = this.body.domProps.centerContainer.height + 'px'; + this.svg.style.height = this.body.domProps.centerContainer.height + 'px'; + } + this.updateSVGheight = false; } - if (text !== undefined) { - this.setText(text); + else { + this.svg.style.height = ('' + this.options.graphHeight).replace('px','') + 'px'; } - // create the frame - this.frame = document.createElement('div'); - this.frame.className = 'network-tooltip'; - this.frame.style.color = style.fontColor; - this.frame.style.backgroundColor = style.color.background; - this.frame.style.borderColor = style.color.border; - this.frame.style.fontSize = style.fontSize + 'px'; - this.frame.style.fontFamily = style.fontFace; - this.container.appendChild(this.frame); - } - - /** - * @param {number} x Horizontal position of the popup window - * @param {number} y Vertical position of the popup window - */ - Popup.prototype.setPosition = function(x, y) { - this.x = parseInt(x); - this.y = parseInt(y); - }; - - /** - * Set the content for the popup window. This can be HTML code or text. - * @param {string | Element} content - */ - Popup.prototype.setText = function(content) { - if (content instanceof Element) { - this.frame.innerHTML = ''; - this.frame.appendChild(content); + // zoomed is here to ensure that animations are shown correctly. + if (resized == true || zoomed == true || this.abortedGraphUpdate == true || forceGraphUpdate == true) { + resized = this._updateGraph() || resized; } else { - this.frame.innerHTML = content; // string containing text or HTML + // move the whole svg while dragging + if (this.lastStart != 0) { + var offset = this.body.range.start - this.lastStart; + var range = this.body.range.end - this.body.range.start; + if (this.props.width != 0) { + var rangePerPixelInv = this.props.width/range; + var xOffset = offset * rangePerPixelInv; + this.svg.style.left = (-this.props.width - xOffset) + 'px'; + } + } } + + this.legendLeft.redraw(); + this.legendRight.redraw(); + return resized; }; + /** - * Show the popup window - * @param {boolean} show Optional. Show or hide the window + * Update and redraw the graph. + * */ - Popup.prototype.show = function (show) { - if (show === undefined) { - show = true; - } - - if (show) { - var height = this.frame.clientHeight; - var width = this.frame.clientWidth; - var maxHeight = this.frame.parentNode.clientHeight; - var maxWidth = this.frame.parentNode.clientWidth; + LineGraph.prototype._updateGraph = function () { + // reset the svg elements + DOMutil.prepareElements(this.svgElements); + if (this.props.width != 0 && this.itemsData != null) { + var group, i; + var preprocessedGroupData = {}; + var processedGroupData = {}; + var groupRanges = {}; + var changeCalled = false; - var top = (this.y - height); - if (top + height + this.padding > maxHeight) { - top = maxHeight - height - this.padding; - } - if (top < this.padding) { - top = this.padding; + // getting group Ids + var groupIds = []; + for (var groupId in this.groups) { + if (this.groups.hasOwnProperty(groupId)) { + group = this.groups[groupId]; + if (group.visible == true && (this.options.groups.visibility[groupId] === undefined || this.options.groups.visibility[groupId] == true)) { + groupIds.push(groupId); + } + } } + if (groupIds.length > 0) { + // this is the range of the SVG canvas + var minDate = this.body.util.toGlobalTime(-this.body.domProps.root.width); + var maxDate = this.body.util.toGlobalTime(2 * this.body.domProps.root.width); + var groupsData = {}; + // fill groups data, this only loads the data we require based on the timewindow + this._getRelevantData(groupIds, groupsData, minDate, maxDate); - var left = this.x; - if (left + width + this.padding > maxWidth) { - left = maxWidth - width - this.padding; - } - if (left < this.padding) { - left = this.padding; - } + // apply sampling, if disabled, it will pass through this function. + this._applySampling(groupIds, groupsData); - this.frame.style.left = left + "px"; - this.frame.style.top = top + "px"; - this.frame.style.visibility = "visible"; - this.hidden = false; - } - else { - this.hide(); - } - }; + // we transform the X coordinates to detect collisions + for (i = 0; i < groupIds.length; i++) { + preprocessedGroupData[groupIds[i]] = this._convertXcoordinates(groupsData[groupIds[i]]); + } - /** - * Hide the popup window - */ - Popup.prototype.hide = function () { - this.hidden = true; - this.frame.style.visibility = "hidden"; - }; + // now all needed data has been collected we start the processing. + this._getYRanges(groupIds, preprocessedGroupData, groupRanges); - module.exports = Popup; + // 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); + var MAX_CYCLES = 5; + if (changeCalled == true && this.COUNTER < MAX_CYCLES) { + DOMutil.cleanupElements(this.svgElements); + this.abortedGraphUpdate = true; + this.COUNTER++; + this.body.emitter.emit('change'); + return true; + } + else { + if (this.COUNTER > MAX_CYCLES) { + console.log("WARNING: there may be an infinite loop in the _updateGraph emitter cycle.") + } + this.COUNTER = 0; + this.abortedGraphUpdate = false; + + // 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[groupIds[i]] = this._convertYcoordinates(groupsData[groupIds[i]], group); + } + // draw the groups + for (i = 0; i < groupIds.length; i++) { + group = this.groups[groupIds[i]]; + if (group.options.style != 'bar') { // bar needs to be drawn enmasse + group.draw(processedGroupData[groupIds[i]], group, this.framework); + } + } + BarGraphFunctions.draw(groupIds, processedGroupData, this.framework); + } + } + } + + // cleanup unused svg elements + DOMutil.cleanupElements(this.svgElements); + return false; + }; -/***/ }, -/* 42 */ -/***/ function(module, exports, __webpack_require__) { /** - * 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 + * 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. * - * @param {String} data Text containing a graph in DOT-notation - * @return {Object} graph An object containing two parameters: - * {Object[]} nodes - * {Object[]} edges + * @param {array} groupIds + * @param {object} groupsData + * @param {date} minDate + * @param {date} maxDate + * @private */ - 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 + LineGraph.prototype._getRelevantData = function (groupIds, groupsData, minDate, maxDate) { + var group, i, j, item; + if (groupIds.length > 0) { + for (i = 0; i < groupIds.length; i++) { + group = this.groups[groupIds[i]]; + groupsData[groupIds[i]] = []; + var dataContainer = groupsData[groupIds[i]]; + // optimization for sorted data + if (group.options.sort == true) { + var guess = Math.max(0, util.binarySearchValue(group.itemsData, minDate, 'x', 'before')); + for (j = guess; j < group.itemsData.length; j++) { + item = group.itemsData[j]; + if (item !== undefined) { + if (item.x > maxDate) { + dataContainer.push(item); + break; + } + else { + dataContainer.push(item); + } + } + } + } + else { + for (j = 0; j < group.itemsData.length; j++) { + item = group.itemsData[j]; + if (item !== undefined) { + if (item.x > minDate && item.x < maxDate) { + dataContainer.push(item); + } + } + } + } + } + } }; - 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 - - /** - * 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); - } - - /** - * 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 + * + * @param groupIds + * @param groupsData + * @private */ - function nextPreview() { - return dot.charAt(index + 1); - } + LineGraph.prototype._applySampling = function (groupIds, groupsData) { + var group; + if (groupIds.length > 0) { + for (var i = 0; i < groupIds.length; i++) { + group = this.groups[groupIds[i]]; + if (group.options.sampling == true) { + var dataContainer = groupsData[groupIds[i]]; + if (dataContainer.length > 0) { + var increment = 1; + var amountOfPoints = dataContainer.length; - /** - * 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); - } + // 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. + var xDistance = this.body.util.toGlobalScreen(dataContainer[dataContainer.length - 1].x) - this.body.util.toGlobalScreen(dataContainer[0].x); + var pointsPerPixel = amountOfPoints / xDistance; + increment = Math.min(Math.ceil(0.2 * amountOfPoints), Math.max(1, Math.round(pointsPerPixel))); - /** - * 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 = {}; - } + var sampledData = []; + for (var j = 0; j < amountOfPoints; j += increment) { + sampledData.push(dataContainer[j]); - if (b) { - for (var name in b) { - if (b.hasOwnProperty(name)) { - a[name] = b[name]; + } + groupsData[groupIds[i]] = sampledData; + } } } } - return a; - } + }; + /** - * 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 + * @param {array} groupIds + * @param {object} groupsData + * @param {object} groupRanges | this is being filled here + * @private */ - 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] = {}; + LineGraph.prototype._getYRanges = function (groupIds, groupsData, groupRanges) { + var groupData, group, i; + var barCombinedDataLeft = []; + var barCombinedDataRight = []; + var options; + if (groupIds.length > 0) { + for (i = 0; i < groupIds.length; i++) { + groupData = groupsData[groupIds[i]]; + options = this.groups[groupIds[i]].options; + if (groupData.length > 0) { + group = this.groups[groupIds[i]]; + // if bar graphs are stacked, their range need to be handled differently and accumulated over all groups. + if (options.barChart.handleOverlap == 'stack' && options.style == 'bar') { + if (options.yAxisOrientation == 'left') {barCombinedDataLeft = barCombinedDataLeft.concat(group.getYRange(groupData)) ;} + else {barCombinedDataRight = barCombinedDataRight.concat(group.getYRange(groupData));} + } + else { + groupRanges[groupIds[i]] = group.getYRange(groupData,groupIds[i]); + } } - o = o[key]; - } - else { - // this is the end point - o[key] = value; } + + // if bar graphs are stacked, their range need to be handled differently and accumulated over all groups. + BarGraphFunctions.getStackedBarYRange(barCombinedDataLeft , groupRanges, groupIds, '__barchartLeft' , 'left' ); + BarGraphFunctions.getStackedBarYRange(barCombinedDataRight, groupRanges, groupIds, '__barchartRight', 'right'); } - } + }; + /** - * 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 + * this sets the Y ranges for the Y axis. It also determines which of the axis should be shown or hidden. + * @param {Array} groupIds + * @param {Object} groupRanges + * @private */ - function addNode(graph, node) { - var i, len; - var current = null; + LineGraph.prototype._updateYAxis = function (groupIds, groupRanges) { + var resized = false; + var yAxisLeftUsed = false; + var yAxisRightUsed = false; + var minLeft = 1e9, minRight = 1e9, maxLeft = -1e9, maxRight = -1e9, minVal, maxVal; + // if groups are present + if (groupIds.length > 0) { + // this is here to make sure that if there are no items in the axis but there are groups, that there is no infinite draw/redraw loop. + for (var i = 0; i < groupIds.length; i++) { + var group = this.groups[groupIds[i]]; + if (group && group.options.yAxisOrientation != 'right') { + yAxisLeftUsed = true; + minLeft = 0; + maxLeft = 0; + } + else if (group && group.options.yAxisOrientation) { + yAxisRightUsed = true; + minRight = 0; + maxRight = 0; + } + } - // 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; - } + // if there are items: + for (var i = 0; i < groupIds.length; i++) { + if (groupRanges.hasOwnProperty(groupIds[i])) { + if (groupRanges[groupIds[i]].ignore !== true) { + minVal = groupRanges[groupIds[i]].min; + maxVal = groupRanges[groupIds[i]].max; - // 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 (groupRanges[groupIds[i]].yAxisOrientation != 'right') { + 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 (!current) { - // this is a new node - current = { - id: node.id - }; - if (graph.node) { - // clone default attributes - current.attr = merge(current.attr, graph.node); + if (yAxisLeftUsed == true) { + this.yAxisLeft.setRange(minLeft, maxLeft); + } + if (yAxisRightUsed == true) { + this.yAxisRight.setRange(minRight, maxRight); } } + resized = this._toggleAxisVisiblity(yAxisLeftUsed , this.yAxisLeft) || resized; + resized = this._toggleAxisVisiblity(yAxisRightUsed, this.yAxisRight) || resized; - // add node to this (sub)graph and all its parent graphs - for (i = graphs.length - 1; i >= 0; i--) { - var g = graphs[i]; + if (yAxisRightUsed == true && yAxisLeftUsed == true) { + this.yAxisLeft.drawIcons = true; + this.yAxisRight.drawIcons = true; + } + else { + this.yAxisLeft.drawIcons = false; + this.yAxisRight.drawIcons = false; + } + this.yAxisRight.master = !yAxisLeftUsed; + if (this.yAxisRight.master == false) { + if (yAxisRightUsed == true) {this.yAxisLeft.lineOffset = this.yAxisRight.width;} + else {this.yAxisLeft.lineOffset = 0;} - if (!g.nodes) { - g.nodes = []; - } - if (g.nodes.indexOf(current) == -1) { - g.nodes.push(current); - } + resized = this.yAxisLeft.redraw() || resized; + this.yAxisRight.stepPixelsForced = this.yAxisLeft.stepPixels; + this.yAxisRight.zeroCrossing = this.yAxisLeft.zeroCrossing; + resized = this.yAxisRight.redraw() || resized; + } + else { + resized = this.yAxisRight.redraw() || resized; } - // merge attributes - if (node.attr) { - current.attr = merge(current.attr, node.attr); + // clean the accumulated lists + if (groupIds.indexOf('__barchartLeft') != -1) { + groupIds.splice(groupIds.indexOf('__barchartLeft'),1); } - } + if (groupIds.indexOf('__barchartRight') != -1) { + groupIds.splice(groupIds.indexOf('__barchartRight'),1); + } + + return resized; + }; + /** - * Add an edge to a graph object - * @param {Object} graph - * @param {Object} edge + * 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 */ - function addEdge(graph, edge) { - if (!graph.edges) { - graph.edges = []; + LineGraph.prototype._toggleAxisVisiblity = function (axisUsed, axis) { + var changed = false; + if (axisUsed == false) { + if (axis.dom.frame.parentNode && axis.hidden == false) { + axis.hide() + changed = true; + } } - graph.edges.push(edge); - if (graph.edge) { - var attr = merge({}, graph.edge); // clone default attributes - edge.attr = merge(attr, edge.attr); // merge attributes + else { + if (!axis.dom.frame.parentNode && axis.hidden == true) { + axis.show(); + changed = true; + } } - } + return changed; + }; + /** - * 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 + * 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 */ - function createEdge(graph, from, to, type, attr) { - var edge = { - from: from, - to: to, - type: type - }; + LineGraph.prototype._convertXcoordinates = function (datapoints) { + var extractedData = []; + var xValue, yValue; + var toScreen = this.body.util.toScreen; - if (graph.edge) { - edge.attr = merge({}, graph.edge); // clone default attributes + for (var i = 0; i < datapoints.length; i++) { + xValue = toScreen(datapoints[i].x) + this.props.width; + yValue = datapoints[i].y; + extractedData.push({x: xValue, y: yValue}); } - edge.attr = merge(edge.attr || {}, attr); // merge attributes - return edge; - } + return extractedData; + }; + /** - * Get next token in the current dot file. - * The token and token type are available as token and tokenType + * 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 + * @param group + * @returns {Array} + * @private */ - function getToken() { - tokenType = TOKENTYPE.NULL; - token = ''; + LineGraph.prototype._convertYcoordinates = function (datapoints, group) { + var extractedData = []; + var xValue, yValue; + var toScreen = this.body.util.toScreen; + var axis = this.yAxisLeft; + var svgHeight = Number(this.svg.style.height.replace('px','')); + if (group.options.yAxisOrientation == 'right') { + axis = this.yAxisRight; + } - // skip over whitespaces - while (c == ' ' || c == '\t' || c == '\n' || c == '\r') { // space, tab, enter - next(); + for (var i = 0; i < datapoints.length; i++) { + var labelValue; + //if (datapoints[i].label) { + // labelValue = datapoints[i].label; + //} + //else { + // labelValue = null; + //} + labelValue = datapoints[i].label ? datapoints[i].label : null; + xValue = toScreen(datapoints[i].x) + this.props.width; + yValue = Math.round(axis.convertValue(datapoints[i].y)); + extractedData.push({x: xValue, y: yValue, label:labelValue}); } - do { - var isComment = false; + group.setZeroPosition(Math.min(svgHeight, axis.convertValue(0))); - // skip comment - if (c == '#') { - // find the previous non-space character - var i = index - 1; - while (dot.charAt(i) == ' ' || dot.charAt(i) == '\t') { - i--; - } - if (dot.charAt(i) == '\n' || dot.charAt(i) == '') { - // the # is at the start of a line, this is indeed a line comment - while (c != '' && c != '\n') { - next(); - } - isComment = true; - } - } - if (c == '/' && nextPreview() == '/') { - // skip line comment - while (c != '' && c != '\n') { - next(); - } - isComment = true; - } - if (c == '/' && nextPreview() == '*') { - // skip block comment - while (c != '') { - if (c == '*' && nextPreview() == '/') { - // end of block comment found. skip these last two characters - next(); - next(); - break; - } - else { - next(); - } - } - isComment = true; - } + return extractedData; + }; - // skip over whitespaces - while (c == ' ' || c == '\t' || c == '\n' || c == '\r') { // space, tab, enter - next(); - } - } - while (isComment); - // check for end of dot file - if (c == '') { - // token is still empty - tokenType = TOKENTYPE.DELIMITER; - return; - } + module.exports = LineGraph; - // 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; - } +/***/ }, +/* 44 */ +/***/ function(module, exports, __webpack_require__) { - // 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(); + var util = __webpack_require__(1); + var DOMutil = __webpack_require__(6); + var Component = __webpack_require__(23); + var DataStep = __webpack_require__(45); - 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; - } + /** + * A horizontal time axis + * @param {Object} [options] See DataAxis.setOptions for the available + * options. + * @constructor DataAxis + * @extends Component + * @param body + */ + function DataAxis (body, options, svg, linegraphOptions) { + this.id = util.randomUUID(); + this.body = body; - // 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.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, + alignZeros: true, + customRange: { + left: {min:undefined, max:undefined}, + right: {min:undefined, max:undefined} + }, + title: { + left: {text:undefined}, + right: {text:undefined} + }, + format: { + left: {decimals: undefined}, + right: {decimals: undefined} } - next(); - tokenType = TOKENTYPE.IDENTIFIER; - return; - } - - // something unknown is found, wrong characters, a syntax error - tokenType = TOKENTYPE.UNKNOWN; - while (c != '') { - token += c; - next(); - } - throw new SyntaxError('Syntax error in part "' + chop(token, 30) + '"'); - } + }; - /** - * Parse a graph. - * @returns {Object} graph - */ - function parseGraph() { - var graph = {}; + this.linegraphOptions = linegraphOptions; + this.linegraphSVG = svg; + this.props = {}; + this.DOMelements = { // dynamic elements + lines: {}, + labels: {}, + title: {} + }; - first(); - getToken(); + this.dom = {}; - // optional strict keyword - if (token == 'strict') { - graph.strict = true; - getToken(); - } + this.range = {start:0, end:0}; - // graph or digraph keyword - if (token == 'graph' || token == 'digraph') { - graph.type = token; - getToken(); - } + this.options = util.extend({}, this.defaultOptions); + this.conversionFactor = 1; - // optional graph id - if (tokenType == TOKENTYPE.IDENTIFIER) { - graph.id = token; - getToken(); - } + this.setOptions(options); + this.width = Number(('' + this.options.width).replace("px","")); + this.minWidth = this.width; + this.height = this.linegraphSVG.offsetHeight; + this.hidden = false; - // open angle bracket - if (token != '{') { - throw newSyntaxError('Angle bracket { expected'); - } - getToken(); + this.stepPixels = 25; + this.stepPixelsForced = 25; + this.zeroCrossing = -1; - // statements - parseStatements(graph); + this.lineOffset = 0; + this.master = true; + this.svgElements = {}; + this.iconsRemoved = false; - // close angle bracket - if (token != '}') { - throw newSyntaxError('Angle bracket } expected'); - } - getToken(); - // end of file - if (token !== '') { - throw newSyntaxError('End of file expected'); - } - getToken(); + this.groups = {}; + this.amountOfGroups = 0; - // remove temporary default properties - delete graph.node; - delete graph.edge; - delete graph.graph; + // create the HTML DOM + this._create(); - return graph; + var me = this; + this.body.emitter.on("verticalDrag", function() { + me.dom.lineContainer.style.top = me.body.domProps.scrollTop + 'px'; + }); } - /** - * Parse a list with statements. - * @param {Object} graph - */ - function parseStatements (graph) { - while (token !== '' && token != '}') { - parseStatement(graph); - if (token == ';') { - getToken(); - } - } - } + DataAxis.prototype = new Component(); - /** - * Parse a single statement. Can be a an attribute statement, node - * statement, a series of node statements and edge statements, or a - * parameter. - * @param {Object} graph - */ - function parseStatement(graph) { - // parse subgraph - var subgraph = parseSubgraph(graph); - if (subgraph) { - // edge statements - parseEdge(graph, subgraph); - return; + DataAxis.prototype.addGroup = function(label, graphOptions) { + if (!this.groups.hasOwnProperty(label)) { + this.groups[label] = graphOptions; } + this.amountOfGroups += 1; + }; - // parse an attribute statement - var attr = parseAttributeStatement(graph); - if (attr) { - return; - } + DataAxis.prototype.updateGroup = function(label, graphOptions) { + this.groups[label] = graphOptions; + }; - // parse node - if (tokenType != TOKENTYPE.IDENTIFIER) { - throw newSyntaxError('Identifier expected'); + DataAxis.prototype.removeGroup = function(label) { + if (this.groups.hasOwnProperty(label)) { + delete this.groups[label]; + this.amountOfGroups -= 1; } - 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'); + + 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', + 'customRange', + 'title', + 'format', + 'alignZeros' + ]; + util.selectiveExtend(fields, this.options, options); + + this.minWidth = Number(('' + this.options.width).replace("px","")); + + if (redraw == true && this.dom.frame) { + this.hide(); + this.show(); } - graph[id] = token; - getToken(); - // TODO: implement comma separated list with "a_list: ID=ID [','] [a_list] " - } - else { - parseNodeStatement(graph, id); } - } + }; + /** - * Parse a subgraph - * @param {Object} graph parent graph object - * @return {Object | null} subgraph + * Create the HTML DOM for the DataAxis */ - function parseSubgraph (graph) { - var subgraph = null; + 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; - // optional subgraph keyword - if (token == 'subgraph') { - subgraph = {}; - subgraph.type = 'subgraph'; - getToken(); + this.dom.lineContainer = document.createElement('div'); + this.dom.lineContainer.style.width = '100%'; + this.dom.lineContainer.style.height = this.height; + this.dom.lineContainer.style.position = 'relative'; - // optional graph id - if (tokenType == TOKENTYPE.IDENTIFIER) { - subgraph.id = token; - getToken(); - } - } + // 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); + }; - // open angle bracket - if (token == '{') { - getToken(); + DataAxis.prototype._redrawGroupIcons = function () { + DOMutil.prepareElements(this.svgElements); - if (!subgraph) { - subgraph = {}; - } - subgraph.parent = graph; - subgraph.node = graph.node; - subgraph.edge = graph.edge; - subgraph.graph = graph.graph; + var x; + var iconWidth = this.options.iconWidth; + var iconHeight = 15; + var iconOffset = 4; + var y = iconOffset + 0.5 * iconHeight; - // statements - parseStatements(subgraph); + if (this.options.orientation == 'left') { + x = iconOffset; + } + else { + x = this.width - iconWidth - iconOffset; + } - // close angle bracket - if (token != '}') { - throw newSyntaxError('Angle bracket } expected'); + for (var groupId in this.groups) { + if (this.groups.hasOwnProperty(groupId)) { + if (this.groups[groupId].visible == true && (this.linegraphOptions.visibility[groupId] === undefined || this.linegraphOptions.visibility[groupId] == true)) { + this.groups[groupId].drawIcon(x, y, this.svgElements, this.svg, iconWidth, iconHeight); + y += iconHeight + iconOffset; + } } - getToken(); + } - // remove temporary default properties - delete subgraph.node; - delete subgraph.edge; - delete subgraph.graph; - delete subgraph.parent; + DOMutil.cleanupElements(this.svgElements); + this.iconsRemoved = false; + }; - // register at the parent graph - if (!graph.subgraphs) { - graph.subgraphs = []; - } - graph.subgraphs.push(subgraph); + DataAxis.prototype._cleanupIcons = function() { + if (this.iconsRemoved == false) { + DOMutil.prepareElements(this.svgElements); + DOMutil.cleanupElements(this.svgElements); + this.iconsRemoved = true; } - - return subgraph; } /** - * parse an attribute statement like "node [shape=circle fontSize=16]". - * Available keywords are 'node', 'edge', 'graph'. - * The previous list with default attributes will be replaced - * @param {Object} graph - * @returns {String | null} keyword Returns the name of the parsed attribute - * (node, edge, graph), or null if nothing - * is parsed. + * Create the HTML DOM for the DataAxis */ - 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'; + DataAxis.prototype.show = function() { + this.hidden = false; + 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); + } } - else if (token == 'graph') { - getToken(); - // graph attributes - graph.graph = parseAttributeList(); - return 'graph'; + if (!this.dom.lineContainer.parentNode) { + this.body.dom.backgroundHorizontal.appendChild(this.dom.lineContainer); } - - return null; - } + }; /** - * parse a node statement - * @param {Object} graph - * @param {String | Number} id + * Create the HTML DOM for the DataAxis */ - function parseNodeStatement(graph, id) { - // node statement - var node = { - id: id - }; - var attr = parseAttributeList(); - if (attr) { - node.attr = attr; + DataAxis.prototype.hide = function() { + this.hidden = true; + if (this.dom.frame.parentNode) { + this.dom.frame.parentNode.removeChild(this.dom.frame); } - addNode(graph, node); - // edge statements - parseEdge(graph, id); - } + if (this.dom.lineContainer.parentNode) { + this.dom.lineContainer.parentNode.removeChild(this.dom.lineContainer); + } + }; /** - * Parse an edge or a series of edges - * @param {Object} graph - * @param {String | Number} from Id of the from node + * Set a range (start and end) + * @param end + * @param start + * @param end */ - 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(); + DataAxis.prototype.setRange = function (start, end) { + if (this.master == false && this.options.alignZeros == true && this.zeroCrossing != -1) { + if (start > 0) { + start = 0; } - - // parse edge attributes - var attr = parseAttributeList(); - - // create edge - var edge = createEdge(graph, from, to, type, attr); - addEdge(graph, edge); - - from = to; } - } + this.range.start = start; + this.range.end = end; + }; /** - * Parse a set with attributes, - * for example [label="1.000", shape=solid] - * @return {Object | null} attr + * Repaint the component + * @return {boolean} Returns true if the component is resized */ - function parseAttributeList() { - var attr = null; + DataAxis.prototype.redraw = function () { + var resized = false; + var activeGroups = 0; + + // Make sure the line container adheres to the vertical scrolling. + this.dom.lineContainer.style.top = this.body.domProps.scrollTop + 'px'; - while (token == '[') { - getToken(); - attr = {}; - while (token !== '' && token != ']') { - if (tokenType != TOKENTYPE.IDENTIFIER) { - throw newSyntaxError('Attribute name expected'); + for (var groupId in this.groups) { + if (this.groups.hasOwnProperty(groupId)) { + if (this.groups[groupId].visible == true && (this.linegraphOptions.visibility[groupId] === undefined || this.linegraphOptions.visibility[groupId] == true)) { + activeGroups++; } - var name = token; + } + } + if (this.amountOfGroups == 0 || activeGroups == 0) { + this.hide(); + } + else { + this.show(); + this.height = Number(this.linegraphSVG.style.height.replace("px","")); - getToken(); - if (token != '=') { - throw newSyntaxError('Equal sign = expected'); - } - getToken(); + // 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; - if (tokenType != TOKENTYPE.IDENTIFIER) { - throw newSyntaxError('Attribute value expected'); - } - var value = token; - setValue(attr, name, value); // name can be a path + var props = this.props; + var frame = this.dom.frame; - getToken(); - if (token ==',') { - getToken(); - } - } + // update classname + frame.className = 'dataaxis'; - if (token != ']') { - throw newSyntaxError('Bracket ] expected'); - } - getToken(); - } + // calculate character width and height + this._calculateCharSize(); - return attr; - } + var orientation = this.options.orientation; + var showMinorLabels = this.options.showMinorLabels; + var showMajorLabels = this.options.showMajorLabels; - /** - * 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 + ')'); - } + // determine the width and height of the elements for the axis + props.minorLabelHeight = showMinorLabels ? props.minorCharHeight : 0; + props.majorLabelHeight = showMajorLabels ? props.majorCharHeight : 0; - /** - * 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) + '...'); - } + 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; - /** - * 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 (Array.isArray(array1)) { - array1.forEach(function (elem1) { - if (Array.isArray(array2)) { - array2.forEach(function (elem2) { - fn(elem1, elem2); - }); - } - else { - fn(elem1, array2); - } - }); - } - else { - if (Array.isArray(array2)) { - array2.forEach(function (elem2) { - fn(array1, elem2); - }); + // 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"; + this.props.width = this.body.domProps.left.width; + this.props.height = this.body.domProps.left.height; + } + 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"; + this.props.width = this.body.domProps.right.width; + this.props.height = this.body.domProps.right.height; + } + + resized = this._redrawLabels(); + resized = this._isResized() || resized; + + if (this.options.icons == true) { + this._redrawGroupIcons(); } else { - fn(array1, array2); + this._cleanupIcons(); } + + this._redrawTitle(orientation); } - } + return resized; + }; /** - * 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 + * Repaint major and minor text labels and vertical grid lines + * @private */ - function DOTToGraph (data) { - // parse the DOT file - var dotData = parseDOT(data); - var graphData = { - nodes: [], - edges: [], - options: {} - }; + DataAxis.prototype._redrawLabels = function () { + var resized = false; + DOMutil.prepareElements(this.DOMelements.lines); + DOMutil.prepareElements(this.DOMelements.labels); - // 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 orientation = this.options['orientation']; - // copy the edges - if (dotData.edges) { - /** - * Convert an edge in DOT format to an edge with VisGraph format - * @param {Object} dotEdge - * @returns {Object} graphEdge - */ - var convertEdge = function (dotEdge) { - var graphEdge = { - from: dotEdge.from, - to: dotEdge.to - }; - merge(graphEdge, dotEdge.attr); - graphEdge.style = (dotEdge.type == '->') ? 'arrow' : 'line'; - return graphEdge; - } + // 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; - dotData.edges.forEach(function (dotEdge) { - var from, to; - if (dotEdge.from instanceof Object) { - from = dotEdge.from.nodes; - } - else { - from = { - id: dotEdge.from - } - } + var step = new DataStep( + this.range.start, + this.range.end, + minimumStep, + this.dom.frame.offsetHeight, + this.options.customRange[this.options.orientation], + this.master == false && this.options.alignZeros // doess the step have to align zeros? only if not master and the options is on + ); - if (dotEdge.to instanceof Object) { - to = dotEdge.to.nodes; - } - else { - to = { - id: dotEdge.to - } - } + this.step = step; + // get the distance in pixels for a step + // dead space is space that is "left over" after a step + var stepPixels = (this.dom.frame.offsetHeight - (step.deadSpace * (this.dom.frame.offsetHeight / step.marginRange))) / (((step.marginRange - step.deadSpace) / step.step)); - if (dotEdge.from instanceof Object && dotEdge.from.edges) { - dotEdge.from.edges.forEach(function (subEdge) { - var graphEdge = convertEdge(subEdge); - graphData.edges.push(graphEdge); - }); - } + this.stepPixels = stepPixels; - 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); - }); + var amountOfSteps = this.height / stepPixels; + var stepDifference = 0; - if (dotEdge.to instanceof Object && dotEdge.to.edges) { - dotEdge.to.edges.forEach(function (subEdge) { - var graphEdge = convertEdge(subEdge); - graphData.edges.push(graphEdge); - }); + // the slave axis needs to use the same horizontal lines as the master axis. + if (this.master == false) { + stepPixels = this.stepPixelsForced; + stepDifference = Math.round((this.dom.frame.offsetHeight / stepPixels) - amountOfSteps); + for (var i = 0; i < 0.5 * stepDifference; i++) { + step.previous(); + } + amountOfSteps = this.height / stepPixels; + + if (this.zeroCrossing != -1 && this.options.alignZeros == true) { + var zeroStepDifference = (step.marginEnd / step.step) - this.zeroCrossing; + if (zeroStepDifference > 0) { + for (var i = 0; i < zeroStepDifference; i++) {step.next();} } - }); + else if (zeroStepDifference < 0) { + for (var i = 0; i < -zeroStepDifference; i++) {step.previous();} + } + } } - - // copy the options - if (dotData.attr) { - graphData.options = dotData.attr; + else { + amountOfSteps += 0.25; } - return graphData; - } - - // exports - exports.parseDOT = parseDOT; - exports.DOTToGraph = DOTToGraph; - -/***/ }, -/* 43 */ -/***/ function(module, exports, __webpack_require__) { + this.valueAtZero = step.marginEnd; + var marginStartPos = 0; - - function parseGephi(gephiJSON, options) { - var edges = []; - var nodes = []; - this.options = { - edges: { - inheritColor: true - }, - nodes: { - allowedToMove: false, - parseColor: false - } - }; + // do not draw the first label + var max = 1; - if (options !== undefined) { - this.options.nodes['allowedToMove'] = options.allowedToMove | false; - this.options.nodes['parseColor'] = options.parseColor | false; - this.options.edges['inheritColor'] = options.inheritColor | true; + // Get the number of decimal places + var decimals; + if(this.options.format[orientation] !== undefined) { + decimals = this.options.format[orientation].decimals; } - 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); - } + this.maxLabelSize = 0; + var y = 0; + while (max < Math.round(amountOfSteps)) { + step.next(); + y = Math.round(max * stepPixels); + marginStartPos = max * stepPixels; + var isMajor = step.isMajor(); - 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; + if (this.options['showMinorLabels'] && isMajor == false || this.master == false && this.options['showMinorLabels'] == true) { + this._redrawLabel(y - 2, step.getCurrent(decimals), orientation, 'yAxis minor', this.props.minorCharHeight); + } + + 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(decimals), orientation, 'yAxis major', this.props.majorCharHeight); + } + this._redrawLine(y, orientation, 'grid horizontal major', this.options.majorLinesOffset, this.props.majorLineWidth); } else { - node['color'] = gNode.color !== undefined ? {background:gNode.color, border:gNode.color} : undefined; + this._redrawLine(y, orientation, 'grid horizontal minor', this.options.minorLinesOffset, this.props.minorLineWidth); } - node['radius'] = gNode.size; - node['allowedToMoveX'] = this.options.nodes.allowedToMove; - node['allowedToMoveY'] = this.options.nodes.allowedToMove; - nodes.push(node); - } - return {nodes:nodes, edges:edges}; - } + if (this.master == true && step.current == 0) { + this.zeroCrossing = max; + } - exports.parseGephi = parseGephi; + max++; + } -/***/ }, -/* 44 */ -/***/ function(module, exports, __webpack_require__) { + if (this.master == false) { + this.conversionFactor = y / (this.valueAtZero - step.current); + } + else { + this.conversionFactor = this.dom.frame.offsetHeight / step.marginRange; + } - // 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__(59); + // Note that title is rotated, so we're using the height, not width! + var titleWidth = 0; + if (this.options.title[orientation] !== undefined && this.options.title[orientation].text !== undefined) { + titleWidth = this.props.titleCharHeight; + } + var offset = this.options.icons == true ? Math.max(this.options.iconWidth, titleWidth) + this.options.labelOffsetX + 15 : titleWidth + this.options.labelOffsetX + 15; + + // this will resize the yAxis to accommodate the labels. + if (this.maxLabelSize > (this.width - offset) && this.options.visible == true) { + this.width = this.maxLabelSize + offset; + this.options.width = this.width + "px"; + DOMutil.cleanupElements(this.DOMelements.lines); + DOMutil.cleanupElements(this.DOMelements.labels); + this.redraw(); + resized = 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(); + resized = true; + } + else { + DOMutil.cleanupElements(this.DOMelements.lines); + DOMutil.cleanupElements(this.DOMelements.labels); + resized = false; + } + return resized; + }; -/***/ }, -/* 45 */ -/***/ function(module, exports, __webpack_require__) { + DataAxis.prototype.convertValue = function (value) { + var invertedValue = this.valueAtZero - value; + var convertedValue = invertedValue * this.conversionFactor; + return convertedValue; + }; - // 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__(57); - } - else { - module.exports = function () { - throw Error('hammer.js is only available in a browser, not in node.js.'); + /** + * Create a label for the axis at position x + * @private + * @param y + * @param text + * @param orientation + * @param className + * @param characterHeight + */ + 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'; -/***/ }, -/* 46 */ -/***/ function(module, exports, __webpack_require__) { + text += ''; - var Emitter = __webpack_require__(56); - var Hammer = __webpack_require__(45); - var util = __webpack_require__(1); - var DataSet = __webpack_require__(3); - var DataView = __webpack_require__(4); - var Range = __webpack_require__(17); - var ItemSet = __webpack_require__(27); - var Activator = __webpack_require__(55); - var DateUtil = __webpack_require__(15); + var largestWidth = Math.max(this.props.majorCharWidth,this.props.minorCharWidth); + if (this.maxLabelSize < text.length * largestWidth) { + this.maxLabelSize = text.length * largestWidth; + } + }; /** - * 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 + * Create a minor line for the axis at position y + * @param y + * @param orientation + * @param className + * @param offset + * @param width */ - function Core () {} + 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 = ''; - // turn Core into an event emitter - Emitter(Core.prototype); + 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'; + } + }; /** - * 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. + * Create a title for the axis * @private + * @param orientation */ - Core.prototype._create = function (container) { - this.dom = {}; - - this.dom.root = document.createElement('div'); - this.dom.background = document.createElement('div'); - this.dom.backgroundVertical = document.createElement('div'); - this.dom.backgroundHorizontal = document.createElement('div'); - this.dom.centerContainer = document.createElement('div'); - this.dom.leftContainer = document.createElement('div'); - this.dom.rightContainer = document.createElement('div'); - this.dom.center = document.createElement('div'); - this.dom.left = document.createElement('div'); - this.dom.right = document.createElement('div'); - this.dom.top = document.createElement('div'); - this.dom.bottom = document.createElement('div'); - this.dom.shadowTop = document.createElement('div'); - this.dom.shadowBottom = document.createElement('div'); - this.dom.shadowTopLeft = document.createElement('div'); - this.dom.shadowBottomLeft = document.createElement('div'); - this.dom.shadowTopRight = document.createElement('div'); - this.dom.shadowBottomRight = document.createElement('div'); - - this.dom.root.className = 'vis timeline root'; - 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); + DataAxis.prototype._redrawTitle = function (orientation) { + DOMutil.prepareElements(this.DOMelements.title); - 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); + // Check if the title is defined for this axes + if (this.options.title[orientation] !== undefined && this.options.title[orientation].text !== undefined) { + var title = DOMutil.getDOMElement('div', this.DOMelements.title, this.dom.frame); + title.className = 'yAxis title ' + orientation; + title.innerHTML = this.options.title[orientation].text; - this.on('rangechange', 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)); + // Add style - if provided + if (this.options.title[orientation].style !== undefined) { + util.addCssText(title, this.options.title[orientation].style); + } - var me = this; - this.on('change', function (properties) { - if (properties && properties.queue == true) { - // redraw once on next tick - if (!me._redrawTimer) { - me._redrawTimer = setTimeout(function () { - me._redrawTimer = null; - me._redraw(); - }, 0) - } + if (orientation == 'left') { + title.style.left = this.props.titleCharHeight + 'px'; } else { - // redraw immediately - me._redraw(); + title.style.right = this.props.titleCharHeight + 'px'; } - }); - // create event listeners for all interesting events, these events will be - // emitted via emitter - this.hammer = Hammer(this.dom.root, { - preventDefault: true - }); - this.listeners = {}; + title.style.width = this.height + 'px'; + } - 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)); - if (me.isActive()) { - me.emit.apply(me, args); - } - }; - me.hammer.on(event, listener); - me.listeners[event] = listener; - }); + // we need to clean up in case we did not use all elements. + DOMutil.cleanupElements(this.DOMelements.title); + }; - // 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 - this.redrawCount = 0; - // attach the root panel to the provided container - if (!container) throw new Error('No container provided'); - container.appendChild(this.dom.root); - }; /** - * 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 + * 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 */ - Core.prototype.setOptions = function (options) { - if (options) { - // copy the known options - var fields = ['width', 'height', 'minHeight', 'maxHeight', 'autoResize', 'start', 'end', 'orientation', 'clickToUse', 'dataAttributes', 'hiddenDates']; - util.selectiveExtend(fields, this.options, options); - - if ('hiddenDates' in this.options) { - DateUtil.convertHiddenOptions(this.body, this.options.hiddenDates); - } + 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); - if ('clickToUse' in options) { - if (options.clickToUse) { - if (!this.activator) { - this.activator = new Activator(this.dom.root); - } - } - else { - if (this.activator) { - this.activator.destroy(); - delete this.activator; - } - } - } + this.props.minorCharHeight = measureCharMinor.clientHeight; + this.props.minorCharWidth = measureCharMinor.clientWidth; - // enable/disable autoResize - this._initAutoResize(); + this.dom.frame.removeChild(measureCharMinor); } - // propagate options to all components - this.components.forEach(function (component) { - component.setOptions(options); - }); + 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); - // 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.'); + this.props.majorCharHeight = measureCharMajor.clientHeight; + this.props.majorCharWidth = measureCharMajor.clientWidth; + + this.dom.frame.removeChild(measureCharMajor); } - // redraw everything - this._redraw(); - }; + if (!('titleCharHeight' in this.props)) { + var textTitle = document.createTextNode('0'); + var measureCharTitle = document.createElement('div'); + measureCharTitle.className = 'yAxis title measure'; + measureCharTitle.appendChild(textTitle); + this.dom.frame.appendChild(measureCharTitle); - /** - * Returns true when the Timeline is active. - * @returns {boolean} - */ - Core.prototype.isActive = function () { - return !this.activator || this.activator.active; + this.props.titleCharHeight = measureCharTitle.clientHeight; + this.props.titleCharWidth = measureCharTitle.clientWidth; + + this.dom.frame.removeChild(measureCharTitle); + } }; + module.exports = DataAxis; + + +/***/ }, +/* 45 */ +/***/ function(module, exports, __webpack_require__) { + /** - * Destroy the Core, clean up all DOM elements and event listeners. + * @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 */ - Core.prototype.destroy = function () { - // unbind datasets - this.clear(); - - // remove all event listeners - this.off(); + function DataStep(start, end, minimumStep, containerHeight, customRange, alignZeros) { + // variables + this.current = 0; - // stop checking for changed size - this._stopAutoResize(); + this.autoScale = true; + this.stepIndex = 0; + this.step = 1; + this.scale = 1; - // remove from DOM - if (this.dom.root.parentNode) { - this.dom.root.parentNode.removeChild(this.dom.root); - } - this.dom = null; + this.marginStart; + this.marginEnd; + this.deadSpace = 0; - // remove Activator - if (this.activator) { - this.activator.destroy(); - delete this.activator; - } + this.majorSteps = [1, 2, 5, 10]; + this.minorSteps = [0.25, 0.5, 1, 2]; - // cleanup hammer touch events - for (var event in this.listeners) { - if (this.listeners.hasOwnProperty(event)) { - delete this.listeners[event]; - } - } - this.listeners = null; - this.hammer = null; + this.alignZeros = alignZeros; - // give all components the opportunity to cleanup - this.components.forEach(function (component) { - component.destroy(); - }); + this.setRange(start, end, minimumStep, containerHeight, customRange); + } - this.body = null; - }; /** - * Set a custom time bar - * @param {Date} time + * 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 */ - Core.prototype.setCustomTime = function (time) { - if (!this.customTime) { - throw new Error('Cannot get custom time: Custom time bar is not enabled'); + DataStep.prototype.setRange = function(start, end, minimumStep, containerHeight, customRange) { + this._start = customRange.min === undefined ? start : customRange.min; + this._end = customRange.max === undefined ? end : customRange.max; + + if (this._start == this._end) { + this._start -= 0.75; + this._end += 1; } - this.customTime.setCustomTime(time); + if (this.autoScale == true) { + this.setMinimumStep(minimumStep, containerHeight); + } + + this.setFirst(customRange); }; /** - * Retrieve the current custom time. - * @return {Date} customTime + * Automatically determine the scale that bests fits the provided minimum step + * @param {Number} [minimumStep] The minimum step size in milliseconds */ - Core.prototype.getCustomTime = function() { - if (!this.customTime) { - throw new Error('Cannot get custom time: Custom time bar is not enabled'); - } + DataStep.prototype.setMinimumStep = function(minimumStep, containerHeight) { + // round to floor + var size = this._end - this._start; + var safeSize = size * 1.2; + var minimumStepValue = minimumStep * (safeSize / containerHeight); + var orderOfMagnitude = Math.round(Math.log(safeSize)/Math.LN10); - return this.customTime.getCustomTime(); - }; + var minorStepIdx = -1; + var magnitudefactor = Math.pow(10,orderOfMagnitude); + var start = 0; + if (orderOfMagnitude < 0) { + start = orderOfMagnitude; + } - /** - * Get the id's of the currently visible items. - * @returns {Array} The ids of the visible items - */ - Core.prototype.getVisibleItems = function() { - return this.itemSet && this.itemSet.getVisibleItems() || []; + 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]; }; /** - * 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} + * Round the current date to the first minor date value + * This must be executed once when the current date is set to start Date */ - Core.prototype.clear = function(what) { - // clear items - if (!what || what.items) { - this.setItems(null); + DataStep.prototype.setFirst = function(customRange) { + if (customRange === undefined) { + customRange = {}; } - // clear groups - if (!what || what.groups) { - this.setGroups(null); + var niceStart = customRange.min === undefined ? this._start - (this.scale * 2 * this.minorSteps[this.stepIndex]) : customRange.min; + var niceEnd = customRange.max === undefined ? this._end + (this.scale * this.minorSteps[this.stepIndex]) : customRange.max; + + this.marginEnd = customRange.max === undefined ? this.roundToMinor(niceEnd) : customRange.max; + this.marginStart = customRange.min === undefined ? this.roundToMinor(niceStart) : customRange.min; + + // if we need to align the zero's we need to make sure that there is a zero to use. + if (this.alignZeros == true && (this.marginEnd - this.marginStart) % this.step != 0) { + this.marginEnd += this.marginEnd % this.step; } - // clear options of timeline and of each of the components - if (!what || what.options) { - this.components.forEach(function (component) { - component.setOptions(component.defaultOptions); - }); + this.deadSpace = this.roundToMinor(niceEnd) - niceEnd + this.roundToMinor(niceStart) - niceStart; + this.marginRange = this.marginEnd - this.marginStart; - this.setOptions(this.defaultOptions); // this will also do a redraw + + this.current = this.marginEnd; + }; + + DataStep.prototype.roundToMinor = function(value) { + var rounded = value - (value % (this.scale * this.minorSteps[this.stepIndex])); + if (value % (this.scale * this.minorSteps[this.stepIndex]) > 0.5 * (this.scale * this.minorSteps[this.stepIndex])) { + return rounded + (this.scale * this.minorSteps[this.stepIndex]); } + else { + return rounded; + } + } + + + /** + * 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); }; /** - * Set Core window such that it fits all items - * @param {Object} [options] Available options: - * `animate: boolean | number` - * If true (default), the range is animated - * smoothly to the new window. - * If a number, the number is taken as duration - * for the animation. Default duration is 500 ms. + * Do the next step */ - Core.prototype.fit = function(options) { - var range = this._getDataRange(); + DataStep.prototype.next = function() { + var prev = this.current; + this.current -= this.step; - // skip range set if there is no start and end date - if (range.start === null && range.end === null) { - return; + // safety mechanism: if current time is still unchanged, move to the end + if (this.current == prev) { + this.current = this._end; } - - var animate = (options && options.animate !== undefined) ? options.animate : true; - this.range.setRange(range.start, range.end, animate); }; /** - * Calculate the data range of the items and applies a 5% window around it. - * @returns {{start: Date | null, end: Date | null}} - * @protected + * Do the next step */ - Core.prototype._getDataRange = function() { - // apply the data range as range - var dataRange = this.getItemRange(); + DataStep.prototype.previous = function() { + this.current += this.step; + this.marginEnd += this.step; + this.marginRange = this.marginEnd - this.marginStart; + }; - // 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); - } - return { - start: start, - end: end - } - }; /** - * Set the visible window. Both parameters are optional, you can change only - * start or only end. Syntax: - * - * TimeLine.setWindow(start, end) - * TimeLine.setWindow(start, end, options) - * 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 - * @param {Object} [options] Available options: - * `animate: boolean | number` - * If true (default), the range is animated - * smoothly to the new window. - * If a number, the number is taken as duration - * for the animation. Default duration is 500 ms. + * Get the current datetime + * @return {String} current The current date */ - Core.prototype.setWindow = function(start, end, options) { - var animate; - if (arguments.length == 1) { - var range = arguments[0]; - animate = (range.animate !== undefined) ? range.animate : true; - this.range.setRange(range.start, range.end, animate); + DataStep.prototype.getCurrent = function(decimals) { + // prevent round-off errors when close to zero + var current = (Math.abs(this.current) < this.step / 2) ? 0 : this.current; + var toPrecision = '' + Number(current).toPrecision(5); + + // If decimals is specified, then limit or extend the string as required + if(decimals !== undefined && !isNaN(Number(decimals))) { + // If string includes exponent, then we need to add it to the end + var exp = ""; + var index = toPrecision.indexOf("e"); + if(index != -1) { + // Get the exponent + exp = toPrecision.slice(index); + // Remove the exponent in case we need to zero-extend + toPrecision = toPrecision.slice(0, index); + } + index = Math.max(toPrecision.indexOf(","), toPrecision.indexOf(".")); + if(index === -1) { + // No decimal found - if we want decimals, then we need to add it + if(decimals !== 0) { + toPrecision += '.'; + } + // Calculate how long the string should be + index = toPrecision.length + decimals; + } + else if(decimals !== 0) { + // Calculate how long the string should be - accounting for the decimal place + index += decimals + 1; + } + if(index > toPrecision.length) { + // We need to add zeros! + for(var cnt = index - toPrecision.length; cnt > 0; cnt--) { + toPrecision += '0'; + } + } + else { + // we need to remove characters + toPrecision = toPrecision.slice(0, index); + } + // Add the exponent if there is one + toPrecision += exp; } else { - animate = (options && options.animate !== undefined) ? options.animate : true; - this.range.setRange(start, end, animate); + if (toPrecision.indexOf(",") != -1 || toPrecision.indexOf(".") != -1) { + // If no decimal is specified, and there are decimal places, remove trailing zeros + 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; + } + } + } } + + return toPrecision; }; /** - * Move the window such that given time is centered on screen. - * @param {Date | Number | String} time - * @param {Object} [options] Available options: - * `animate: boolean | number` - * If true (default), the range is animated - * smoothly to the new window. - * If a number, the number is taken as duration - * for the animation. Default duration is 500 ms. + * 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. */ - Core.prototype.moveTo = function(time, options) { - var interval = this.range.end - this.range.start; - var t = util.convert(time, 'Date').valueOf(); + DataStep.prototype.isMajor = function() { + return (this.current % (this.scale * this.majorSteps[this.stepIndex]) == 0); + }; - var start = t - interval / 2; - var end = t + interval / 2; - var animate = (options && options.animate !== undefined) ? options.animate : true; + module.exports = DataStep; - this.range.setRange(start, end, animate); - }; - /** - * 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) - }; - }; +/***/ }, +/* 46 */ +/***/ function(module, exports, __webpack_require__) { - /** - * Force a redraw. Can be overridden by implementations of Core - */ - Core.prototype.redraw = function() { - this._redraw(); - }; + var util = __webpack_require__(1); + var DOMutil = __webpack_require__(6); + var Line = __webpack_require__(47); + var Bar = __webpack_require__(49); + var Points = __webpack_require__(48); /** - * Redraw for internal use. Redraws all components. See also the public - * method redraw. - * @protected + * /** + * @param {object} group | the object of the group from the dataset + * @param {string} groupId | ID of the group + * @param {object} options | the default options + * @param {array} groupsUsingDefaultStyles | this array has one entree. + * It is passed as an array so it is passed by reference. + * It enumerates through the default styles + * @constructor */ - Core.prototype._redraw = function() { - var resized = false; - var options = this.options; - var props = this.props; - var dom = this.dom; - - if (!dom) return; // when destroyed + 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; + } - DateUtil.updateHiddenDates(this.body, this.options.hiddenDates); - // update class names - if (options.orientation == 'top') { - util.addClassName(dom.root, 'top'); - util.removeClassName(dom.root, 'bottom'); + /** + * this loads a reference to all items in this group into this group. + * @param {array} items + */ + 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 { - util.removeClassName(dom.root, 'top'); - util.addClassName(dom.root, 'bottom'); + this.itemsData = []; } + }; - // 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; - // workaround for a bug in IE: the clientWidth of an element with - // a height:0px and overflow:hidden is not calculated and always has value 0 - if (dom.centerContainer.clientHeight === 0) { - props.border.left = props.border.top; - props.border.right = props.border.left; - } - if (dom.root.clientHeight === 0) { - borderRootWidth = borderRootHeight; - } + /** + * this is used for plotting barcharts, this way, we only have to calculate it once. + * @param pos + */ + GraphGroup.prototype.setZeroPosition = function(pos) { + this.zeroPosition = pos; + }; - // 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. + /** + * set the options of the graph group over the default options. + * @param options + */ + GraphGroup.prototype.setOptions = function(options) { + if (options !== undefined) { + var fields = ['sampling','style','sort','yAxisOrientation','barChart']; + util.selectiveDeepExtend(fields, this.options, options); - // 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'); + util.mergeOptions(this.options, options,'catmullRom'); + util.mergeOptions(this.options, options,'drawPoints'); + util.mergeOptions(this.options, options,'shaded'); - // 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; + 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; + } + } + } + } + } - // 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; + if (this.options.style == 'line') { + this.type = new Line(this.id, this.options); + } + else if (this.options.style == 'bar') { + this.type = new Bar(this.id, this.options); + } + else if (this.options.style == 'points') { + this.type = new Points(this.id, this.options); + } + }; - // 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'; + /** + * this updates the current group class with the latest group dataset entree, used in _updateGroup in linegraph + * @param group + */ + 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.style = group.style; + this.setOptions(group.options); + }; - // reposition the panels - dom.background.style.left = '0'; - dom.background.style.top = '0'; - dom.backgroundVertical.style.left = (props.left.width + props.border.left) + '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(); + /** + * draw the icon for the legend. + * + * @param x + * @param y + * @param JSONcontainer + * @param SVGcontainer + * @param iconWidth + * @param iconHeight + */ + GraphGroup.prototype.drawIcon = function(x, y, JSONcontainer, SVGcontainer, iconWidth, iconHeight) { + var fillHeight = iconHeight * 0.5; + var path, fillPath; - // 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'; + 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"); - // 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; + if (this.options.style == 'line') { + path = DOMutil.getSVGElement("path", JSONcontainer, SVGcontainer); + path.setAttributeNS(null, "class", this.className); + if(this.style !== undefined) { + path.setAttributeNS(null, "style", this.style); + } - // redraw all components - this.components.forEach(function (component) { - resized = component.redraw() || resized; - }); - if (resized) { - // keep repainting until all sizes are settled - var MAX_REDRAWS = 3; // maximum number of consecutive redraws - if (this.redrawCount < MAX_REDRAWS) { - this.redrawCount++; - this._redraw(); + 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"); } - else { - console.log('WARNING: infinite loop in redraw?'); + + if (this.options.drawPoints.enabled == true) { + DOMutil.drawPoint(x + 0.5 * iconWidth,y, this, JSONcontainer, SVGcontainer); } - this.redrawCount = 0; } + else { + var barWidth = Math.round(0.3 * iconWidth); + var bar1Height = Math.round(0.4 * iconHeight); + var bar2Height = Math.round(0.75 * iconHeight); - this.emit("finishedRedraw"); - }; - - // TODO: deprecated since version 1.1.0, remove some day - Core.prototype.repaint = function () { - throw new Error('Function repaint is deprecated. Use redraw instead.'); - }; + var offset = Math.round((iconWidth - (2 * barWidth))/3); - /** - * Set a current time. This can be used for example to ensure that a client's - * time is synchronized with a shared server time. - * Only applicable when option `showCurrentTime` is true. - * @param {Date | String | Number} time A Date, unix timestamp, or - * ISO date string. - */ - Core.prototype.setCurrentTime = function(time) { - if (!this.currentTime) { - throw new Error('Option showCurrentTime must be true'); + 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); } - - this.currentTime.setCurrentTime(time); }; + /** - * Get the current time. - * Only applicable when option `showCurrentTime` is true. - * @return {Date} Returns the current time. + * return the legend entree for this group. + * + * @param iconWidth + * @param iconHeight + * @returns {{icon: HTMLElement, label: (group.content|*|string), orientation: (.options.yAxisOrientation|*)}} */ - Core.prototype.getCurrentTime = function() { - if (!this.currentTime) { - throw new Error('Option showCurrentTime must be true'); - } + 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}; + } - return this.currentTime.getCurrentTime(); - }; + GraphGroup.prototype.getYRange = function(groupData) { + return this.type.getYRange(groupData); + } - /** - * 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) { - return DateUtil.toTime(this, x, this.props.center.width); - }; + GraphGroup.prototype.draw = function(dataset, group, framework) { + this.type.draw(dataset, group, framework); + } - /** - * 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) { - return DateUtil.toTime(this, x, this.props.root.width); - //var conversion = this.range.conversion(this.props.root.width); - //return new Date(x / conversion.scale + conversion.offset); - }; - /** - * Convert a datetime (Date object) into a position on the screen - * @param {Date} time A date - * @return {int} x The position on the screen in pixels which corresponds - * with the given date. - * @private - */ - // TODO: move this function to Range - Core.prototype._toScreen = function(time) { - return DateUtil.toScreen(this, time, this.props.center.width); - }; + module.exports = GraphGroup; +/***/ }, +/* 47 */ +/***/ function(module, exports, __webpack_require__) { /** - * 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 + * Created by Alex on 11/11/2014. */ - // TODO: move this function to Range - Core.prototype._toGlobalScreen = function(time) { - return DateUtil.toScreen(this, time, this.props.root.width); - //var conversion = this.range.conversion(this.props.root.width); - //return (time.valueOf() - conversion.offset) * conversion.scale; - }; + var DOMutil = __webpack_require__(6); + var Points = __webpack_require__(48); + function Line(groupId, options) { + this.groupId = groupId; + this.options = options; + } - /** - * Initialize watching when option autoResize is true - * @private - */ - Core.prototype._initAutoResize = function () { - if (this.options.autoResize == true) { - this._startAutoResize(); - } - else { - this._stopAutoResize(); + Line.prototype.getYRange = function(groupData) { + var yMin = groupData[0].y; + var yMax = groupData[0].y; + for (var j = 0; j < groupData.length; j++) { + yMin = yMin > groupData[j].y ? groupData[j].y : yMin; + yMax = yMax < groupData[j].y ? groupData[j].y : yMax; } + return {min: yMin, max: yMax, yAxisOrientation: this.options.yAxisOrientation}; }; + /** - * Watch for changes in the size of the container. On resize, the Panel will - * automatically redraw itself. - * @private + * draw a line graph + * + * @param dataset + * @param group */ - Core.prototype._startAutoResize = function () { - var me = this; - - this._stopAutoResize(); + Line.prototype.draw = function (dataset, group, framework) { + if (dataset != null) { + if (dataset.length > 0) { + var path, d; + var svgHeight = Number(framework.svg.style.height.replace('px','')); + path = DOMutil.getSVGElement('path', framework.svgElements, framework.svg); + path.setAttributeNS(null, "class", group.className); + if(group.style !== undefined) { + path.setAttributeNS(null, "style", group.style); + } - this._onResize = function() { - if (me.options.autoResize != true) { - // stop watching when the option autoResize is changed to false - me._stopAutoResize(); - return; - } + // construct path from dataset + if (group.options.catmullRom.enabled == true) { + d = Line._catmullRom(dataset, group); + } + else { + d = Line._linear(dataset); + } - if (me.dom.root) { - // check whether the frame is resized - // Note: we compare offsetWidth here, not clientWidth. For some reason, - // IE does not restore the clientWidth from 0 to the actual width after - // changing the timeline's container display style from none to visible - if ((me.dom.root.offsetWidth != me.props.lastWidth) || - (me.dom.root.offsetHeight != me.props.lastHeight)) { - me.props.lastWidth = me.dom.root.offsetWidth; - me.props.lastHeight = me.dom.root.offsetHeight; + // append with points for fill and finalize the path + if (group.options.shaded.enabled == true) { + var fillPath = DOMutil.getSVGElement('path', framework.svgElements, framework.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"); + if(group.options.shaded.style !== undefined) { + fillPath.setAttributeNS(null, "style", group.options.shaded.style); + } + fillPath.setAttributeNS(null, "d", dFill); + } + // copy properties to path for drawing. + path.setAttributeNS(null, 'd', 'M' + d); - me.emit('change'); + // draw points + if (group.options.drawPoints.enabled == true) { + Points.draw(dataset, group, framework); } } - }; - - // 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; - } - // remove event listener on window.resize - util.removeEventListener(window, 'resize', this._onResize); - this._onResize = null; - }; /** - * Start moving the timeline vertically - * @param {Event} event + * 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 */ - Core.prototype._onTouch = function (event) { - this.touch.allowDragging = true; - }; - - /** - * Start moving the timeline vertically - * @param {Event} event - * @private - */ - Core.prototype._onPinch = function (event) { - this.touch.allowDragging = false; - }; - - /** - * Start moving the timeline vertically - * @param {Event} event - * @private - */ - Core.prototype._onDragStart = function (event) { - this.touch.initialScrollTop = this.props.scrollTop; - }; + Line._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++) { - /** - * 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; + p0 = (i == 0) ? data[0] : data[i-1]; + p1 = data[i]; + p2 = data[i+1]; + p3 = (i + 2 < length) ? data[i+2] : p2; - var delta = event.gesture.deltaY; - var oldScrollTop = this._getScrollTop(); - var newScrollTop = this._setScrollTop(this.touch.initialScrollTop + delta); + // 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 }; - if (newScrollTop != oldScrollTop) { - this._redraw(); // TODO: this causes two redraws when dragging, the other is triggered by rangechange already - this.emit("verticalDrag"); + d += 'C' + + bp1.x + ',' + + bp1.y + ' ' + + bp2.x + ',' + + bp2.y + ' ' + + p2.x + ',' + + p2.y + ' '; } - }; - /** - * Apply a scrollTop - * @param {Number} scrollTop - * @returns {Number} scrollTop Returns the applied scrollTop - * @private - */ - Core.prototype._setScrollTop = function (scrollTop) { - this.props.scrollTop = scrollTop; - this._updateScrollTop(); - return this.props.scrollTop; + return d; }; /** - * Update the current scrollTop when the height of the containers has been changed - * @returns {Number} scrollTop Returns the applied scrollTop + * 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 + * @param group + * @returns {string} * @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; + Line._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++) { - // 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; + p0 = (i == 0) ? data[0] : data[i-1]; + p1 = data[i]; + p2 = data[i+1]; + p3 = (i + 2 < length) ? data[i+2] : p2; - return this.props.scrollTop; - }; + 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)); - /** - * Get the current scrollTop - * @returns {number} scrollTop - * @private - */ - Core.prototype._getScrollTop = function () { - return this.props.scrollTop; - }; + // Catmull-Rom to Cubic Bezier conversion matrix - module.exports = Core; + // 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 ] -/***/ }, -/* 47 */ -/***/ function(module, exports, __webpack_require__) { + 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); - var Hammer = __webpack_require__(45); + 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;} - /** - * 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; + bp1 = { x: ((-d2pow2A * p0.x + A*p1.x + d1pow2A * p2.x) * N), + y: ((-d2pow2A * p0.y + A*p1.y + d1pow2A * p2.y) * N)}; - // for hammer.js 1.0.5 - // var gesture = Hammer.event.collectEventData(this, eventType, event); + bp2 = { x: (( d3pow2A * p1.x + B*p2.x - d2pow2A * p3.x) * M), + y: (( d3pow2A * p1.y + B*p2.y - d2pow2A * p3.y) * M)}; - // for hammer.js 1.0.6+ - var touches = Hammer.event.getTouchList(event, eventType); - var gesture = Hammer.event.collectEventData(this, eventType, touches, event); + 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 + ' '; + } - // 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 d; } - - return gesture; - }; - - -/***/ }, -/* 48 */ -/***/ function(module, exports, __webpack_require__) { - - // English - exports['en'] = { - current: 'current', - time: 'time' - }; - exports['en_EN'] = exports['en']; - exports['en_US'] = exports['en']; - - // Dutch - exports['nl'] = { - custom: 'aangepaste', - time: 'tijd' }; - exports['nl_NL'] = exports['nl']; - exports['nl_BE'] = exports['nl']; - - -/***/ }, -/* 49 */ -/***/ function(module, exports, __webpack_require__) { - // English - exports['en'] = { - edit: 'Edit', - del: 'Delete selected', - back: 'Back', - addNode: 'Add Node', - addEdge: 'Add Edge', - editNode: 'Edit Node', - editEdge: 'Edit Edge', - addDescription: 'Click in an empty space to place a new node.', - edgeDescription: '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.', - createEdgeError: 'Cannot link edges to a cluster.', - deleteClusterError: 'Clusters cannot be deleted.' + /** + * this generates the SVG path for a linear drawing between datapoints. + * @param data + * @returns {string} + * @private + */ + Line._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; }; - exports['en_EN'] = exports['en']; - exports['en_US'] = exports['en']; - // Dutch - exports['nl'] = { - edit: 'Wijzigen', - del: 'Selectie verwijderen', - back: 'Terug', - addNode: 'Node toevoegen', - addEdge: 'Link toevoegen', - editNode: 'Node wijzigen', - editEdge: 'Link wijzigen', - addDescription: 'Klik op een leeg gebied om een nieuwe node te maken.', - edgeDescription: 'Klik op een node en sleep de link naar een andere node om ze te verbinden.', - editEdgeDescription: 'Klik op de verbindingspunten en sleep ze naar een node om daarmee te verbinden.', - createEdgeError: 'Kan geen link maken naar een cluster.', - deleteClusterError: 'Clusters kunnen niet worden verwijderd.' - }; - exports['nl_NL'] = exports['nl']; - exports['nl_BE'] = exports['nl']; + module.exports = Line; /***/ }, -/* 50 */ +/* 48 */ /***/ function(module, exports, __webpack_require__) { /** - * Canvas shapes used by Network + * Created by Alex on 11/11/2014. */ - 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(); - - 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) - ); - } - - 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); - }; - - /** - * 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); - }; - - - - /** - * 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 - - this.beginPath(); - this.moveTo(xe, ym); - - this.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); - this.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); - - this.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); - this.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); - - this.lineTo(xe, ymb); - - this.bezierCurveTo(xe, ymb + oy, xm + ox, yeb, xm, yeb); - this.bezierCurveTo(xm - ox, yeb, x, ymb + oy, x, ymb); - - this.lineTo(x, ym); - }; - - - /** - * 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); + var DOMutil = __webpack_require__(6); - // 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); + function Points(groupId, options) { + this.groupId = groupId; + this.options = options; + } - // 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); + Points.prototype.getYRange = function(groupData) { + var yMin = groupData[0].y; + var yMax = groupData[0].y; + for (var j = 0; j < groupData.length; j++) { + yMin = yMin > groupData[j].y ? groupData[j].y : yMin; + yMax = yMax < groupData[j].y ? groupData[j].y : yMax; + } + return {min: yMin, max: yMax, yAxisOrientation: this.options.yAxisOrientation}; + }; - this.beginPath(); - this.moveTo(x, y); - this.lineTo(xl, yl); - this.lineTo(xi, yi); - this.lineTo(xr, yr); - this.closePath(); - }; + Points.prototype.draw = function(dataset, group, framework, offset) { + Points.draw(dataset, group, framework, offset); + } - /** - * 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; - } - }; + /** + * draw the data points + * + * @param {Array} dataset + * @param {Object} JSONcontainer + * @param {Object} svg | SVG DOM element + * @param {GraphGroup} group + * @param {Number} [offset] + */ + Points.draw = function (dataset, group, framework, offset) { + if (offset === undefined) {offset = 0;} + for (var i = 0; i < dataset.length; i++) { + DOMutil.drawPoint(dataset[i].x + offset, dataset[i].y, group, framework.svgElements, framework.svg, dataset[i].label); + } + }; - // TODO: add diamond shape - } + module.exports = Points; /***/ }, -/* 51 */ +/* 49 */ /***/ function(module, exports, __webpack_require__) { /** * Created by Alex on 11/11/2014. */ - var DOMutil = __webpack_require__(2); - var Points = __webpack_require__(53); + var DOMutil = __webpack_require__(6); + var Points = __webpack_require__(48); function Bargraph(groupId, options) { this.groupId = groupId; @@ -23747,7 +22441,8 @@ return /******/ (function(modules) { // webpackBootstrap combinedData.push({ x: processedGroupData[groupIds[i]][j].x, y: processedGroupData[groupIds[i]][j].y, - groupId: groupIds[i] + groupId: groupIds[i], + label: processedGroupData[groupIds[i]][j].label }); barPoints += 1; } @@ -23803,7 +22498,8 @@ return /******/ (function(modules) { // webpackBootstrap DOMutil.drawBar(combinedData[i].x + drawData.offset, combinedData[i].y - heightOffset, drawData.width, group.zeroPosition - combinedData[i].y, group.className + ' bar', framework.svgElements, framework.svg); // draw points if (group.options.drawPoints.enabled == true) { - DOMutil.drawPoint(combinedData[i].x + drawData.offset, combinedData[i].y, group, framework.svgElements, framework.svg); + Points.draw([combinedData[i]], group, framework, drawData.offset); + //DOMutil.drawPoint(combinedData[i].x + drawData.offset, combinedData[i].y, group, framework.svgElements, framework.svg); } } }; @@ -23918,10725 +22614,11220 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = Bargraph; /***/ }, -/* 52 */ +/* 50 */ /***/ function(module, exports, __webpack_require__) { - /** - * Created by Alex on 11/11/2014. - */ - var DOMutil = __webpack_require__(2); - var Points = __webpack_require__(53); - - function Line(groupId, options) { - this.groupId = groupId; - this.options = options; - } - - Line.prototype.getYRange = function(groupData) { - var yMin = groupData[0].y; - var yMax = groupData[0].y; - for (var j = 0; j < groupData.length; j++) { - yMin = yMin > groupData[j].y ? groupData[j].y : yMin; - yMax = yMax < groupData[j].y ? groupData[j].y : yMax; - } - return {min: yMin, max: yMax, yAxisOrientation: this.options.yAxisOrientation}; - }; - + var util = __webpack_require__(1); + var DOMutil = __webpack_require__(6); + var Component = __webpack_require__(23); /** - * draw a line graph - * - * @param dataset - * @param group + * Legend for Graph2d */ - Line.prototype.draw = function (dataset, group, framework) { - if (dataset != null) { - if (dataset.length > 0) { - var path, d; - var svgHeight = Number(framework.svg.style.height.replace('px','')); - path = DOMutil.getSVGElement('path', framework.svgElements, framework.svg); - path.setAttributeNS(null, "class", group.className); - if(group.style !== undefined) { - path.setAttributeNS(null, "style", group.style); - } - - // construct path from dataset - if (group.options.catmullRom.enabled == true) { - d = Line._catmullRom(dataset, group); - } - else { - d = Line._linear(dataset); - } - - // append with points for fill and finalize the path - if (group.options.shaded.enabled == true) { - var fillPath = DOMutil.getSVGElement('path', framework.svgElements, framework.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"); - if(group.options.shaded.style !== undefined) { - fillPath.setAttributeNS(null, "style", group.options.shaded.style); - } - 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) { - Points.draw(dataset, group, framework); - } + function Legend(body, options, side, linegraphOptions) { + 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.linegraphOptions = linegraphOptions; - /** - * 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 - */ - Line._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++) { + this.svgElements = {}; + this.dom = {}; + this.groups = {}; + this.amountOfGroups = 0; + this._create(); - p0 = (i == 0) ? data[0] : data[i-1]; - p1 = data[i]; - p2 = data[i+1]; - p3 = (i + 2 < length) ? data[i+2] : p2; + this.setOptions(options); + } + Legend.prototype = new Component(); - // 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 + Legend.prototype.clear = function() { + this.groups = {}; + this.amountOfGroups = 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 }; + Legend.prototype.addGroup = function(label, graphOptions) { - d += 'C' + - bp1.x + ',' + - bp1.y + ' ' + - bp2.x + ',' + - bp2.y + ' ' + - p2.x + ',' + - p2.y + ' '; + if (!this.groups.hasOwnProperty(label)) { + this.groups[label] = graphOptions; } + this.amountOfGroups += 1; + }; - return d; + Legend.prototype.updateGroup = function(label, graphOptions) { + this.groups[label] = graphOptions; }; - /** - * 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 - * @param group - * @returns {string} - * @private - */ - Line._catmullRom = function(data, group) { - var alpha = group.options.catmullRom.alpha; - if (alpha == 0 || alpha === undefined) { - return this._catmullRomUniform(data); + Legend.prototype.removeGroup = function(label) { + if (this.groups.hasOwnProperty(label)) { + delete this.groups[label]; + this.amountOfGroups -= 1; } - 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 ] - - 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)}; + 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"; - bp2 = { x: (( d3pow2A * p1.x + B*p2.x - d2pow2A * p3.x) * M), - y: (( d3pow2A * p1.y + B*p2.y - d2pow2A * p3.y) * M)}; + this.dom.textArea = document.createElement('div'); + this.dom.textArea.className = 'legendText'; + this.dom.textArea.style.position = "relative"; + this.dom.textArea.style.top = "0px"; - 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 + ' '; - } + this.svg = document.createElementNS('http://www.w3.org/2000/svg',"svg"); + this.svg.style.position = 'absolute'; + this.svg.style.top = 0 +'px'; + this.svg.style.width = this.options.iconSize + 5 + 'px'; + this.svg.style.height = '100%'; - return d; - } + this.dom.frame.appendChild(this.svg); + this.dom.frame.appendChild(this.dom.textArea); }; /** - * this generates the SVG path for a linear drawing between datapoints. - * @param data - * @returns {string} - * @private + * Hide the component from the DOM */ - Line._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; - } + Legend.prototype.hide = function() { + // remove the frame containing the items + if (this.dom.frame.parentNode) { + this.dom.frame.parentNode.removeChild(this.dom.frame); } - return d; }; - module.exports = Line; - - -/***/ }, -/* 53 */ -/***/ function(module, exports, __webpack_require__) { - /** - * Created by Alex on 11/11/2014. + * Show the component in the DOM (when not already visible). + * @return {Boolean} changed */ - var DOMutil = __webpack_require__(2); - - function Points(groupId, options) { - this.groupId = groupId; - this.options = options; - } - - - Points.prototype.getYRange = function(groupData) { - var yMin = groupData[0].y; - var yMax = groupData[0].y; - for (var j = 0; j < groupData.length; j++) { - yMin = yMin > groupData[j].y ? groupData[j].y : yMin; - yMax = yMax < groupData[j].y ? groupData[j].y : yMax; + Legend.prototype.show = function() { + // show frame containing the items + if (!this.dom.frame.parentNode) { + this.body.dom.center.appendChild(this.dom.frame); } - return {min: yMin, max: yMax, yAxisOrientation: this.options.yAxisOrientation}; }; - Points.prototype.draw = function(dataset, group, framework, offset) { - Points.draw(dataset, group, framework, offset); - } - - /** - * draw the data points - * - * @param {Array} dataset - * @param {Object} JSONcontainer - * @param {Object} svg | SVG DOM element - * @param {GraphGroup} group - * @param {Number} [offset] - */ - Points.draw = function (dataset, group, framework, offset) { - if (offset === undefined) {offset = 0;} - for (var i = 0; i < dataset.length; i++) { - DOMutil.drawPoint(dataset[i].x + offset, dataset[i].y, group, framework.svgElements, framework.svg, dataset[i].label); - } + Legend.prototype.setOptions = function(options) { + var fields = ['enabled','orientation','icons','left','right']; + util.selectiveDeepExtend(fields, this.options, options); }; + Legend.prototype.redraw = function() { + var activeGroups = 0; + for (var groupId in this.groups) { + if (this.groups.hasOwnProperty(groupId)) { + if (this.groups[groupId].visible == true && (this.linegraphOptions.visibility[groupId] === undefined || this.linegraphOptions.visibility[groupId] == true)) { + activeGroups++; + } + } + } - module.exports = Points; + 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 = ''; + } -/***/ }, -/* 54 */ -/***/ function(module, exports, __webpack_require__) { + 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 { + var scrollableHeight = this.body.domProps.center.height - this.body.domProps.centerContainer.height; + this.dom.frame.style.bottom = 4 + scrollableHeight + Number(this.body.dom.center.style.top.replace("px","")) + 'px'; + this.dom.frame.style.top = ''; + } - var PhysicsMixin = __webpack_require__(66); - var ClusterMixin = __webpack_require__(60); - var SectorsMixin = __webpack_require__(61); - var SelectionMixin = __webpack_require__(62); - var ManipulationMixin = __webpack_require__(63); - var NavigationMixin = __webpack_require__(64); - var HierarchicalLayoutMixin = __webpack_require__(65); + 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(); + } - /** - * 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]; + var content = ''; + for (var groupId in this.groups) { + if (this.groups.hasOwnProperty(groupId)) { + if (this.groups[groupId].visible == true && (this.linegraphOptions.visibility[groupId] === undefined || this.linegraphOptions.visibility[groupId] == 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.svg.style.width = iconWidth + 5 + iconOffset + 'px'; - /** - * 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; + for (var groupId in this.groups) { + if (this.groups.hasOwnProperty(groupId)) { + if (this.groups[groupId].visible == true && (this.linegraphOptions.visibility[groupId] === undefined || this.linegraphOptions.visibility[groupId] == true)) { + this.groups[groupId].drawIcon(x, y, this.svgElements, this.svg, iconWidth, iconHeight); + y += iconHeight + this.options.iconSpacing; + } + } } + + DOMutil.cleanupElements(this.svgElements); } }; + module.exports = Legend; - /** - * Mixin the physics system and initialize the parameters required. - * - * @private - */ - exports._loadPhysicsSystem = function () { - this._loadMixin(PhysicsMixin); - this._loadSelectedForceSolver(); - if (this.constants.configurePhysics == true) { - this._loadPhysicsConfiguration(); - } - else { - this._cleanupPhysicsConfiguration(); - } - }; +/***/ }, +/* 51 */ +/***/ function(module, exports, __webpack_require__) { - /** - * Mixin the cluster system and initialize the parameters required. - * - * @private - */ - exports._loadClusterSystem = function () { - this.clusterSession = 0; - this.hubThreshold = 5; - this._loadMixin(ClusterMixin); - }; + var Emitter = __webpack_require__(11); + var Hammer = __webpack_require__(19); + var keycharm = __webpack_require__(37); + var util = __webpack_require__(1); + var hammerUtil = __webpack_require__(22); + var DataSet = __webpack_require__(7); + var DataView = __webpack_require__(9); + var dotparser = __webpack_require__(52); + var gephiParser = __webpack_require__(53); + var Groups = __webpack_require__(54); + var Images = __webpack_require__(55); + var Node = __webpack_require__(56); + var Edge = __webpack_require__(57); + var Popup = __webpack_require__(58); + var MixinLoader = __webpack_require__(59); + var Activator = __webpack_require__(36); + var locales = __webpack_require__(70); + // Load custom shapes into CanvasRenderingContext2D + __webpack_require__(71); /** - * Mixin the sector system and initialize the parameters required + * @constructor Network + * Create a network visualization, displaying nodes and edges. * - * @private + * @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 */ - 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); - }; + function Network (container, data, options) { + if (!(this instanceof Network)) { + throw new SyntaxError('Constructor must be called with the new operator'); + } + this._determineBrowserMethod(); + this._initializeMixinLoaders(); - /** - * Mixin the selection system and initialize the parameters required - * - * @private - */ - exports._loadSelectionSystem = function () { - this.selectionObj = {nodes: {}, edges: {}}; + // create variables and set default values + this.containerElement = container; - this._loadMixin(SelectionMixin); - }; + // render and calculation settings + this.renderRefreshRate = 60; // hz (fps) + this.renderTimestep = 1000 / this.renderRefreshRate; // ms -- saves calculation later on + this.renderTime = 0; // measured time it takes to render a frame + this.physicsTime = 0; // measured time it takes to render a frame + this.runDoubleSpeed = false; + this.physicsDiscreteStepsize = 0.50; // discrete stepsize of the simulation + this.initializing = true; - /** - * 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; + this.triggerFunctions = {add:null,edit:null,editEdge:null,connect:null,del:null}; - if (this.constants.dataManipulation.enabled == true) { - // load the manipulator HTML elements. All styling done in css. - if (this.manipulationDiv === undefined) { - this.manipulationDiv = document.createElement('div'); - this.manipulationDiv.className = 'network-manipulationDiv'; - if (this.editMode == true) { - this.manipulationDiv.style.display = "block"; - } - else { - this.manipulationDiv.style.display = "none"; - } - this.frame.appendChild(this.manipulationDiv); + var customScalingFunction = function (min,max,total,value) { + if (max == min) { + return 0.5; } - - if (this.editModeDiv === undefined) { - this.editModeDiv = document.createElement('div'); - this.editModeDiv.className = 'network-manipulation-editMode'; - if (this.editMode == true) { - this.editModeDiv.style.display = "none"; - } - else { - this.editModeDiv.style.display = "block"; - } - this.frame.appendChild(this.editModeDiv); + else { + var scale = 1 / (max - min); + return Math.max(0,(value - min)*scale); } + }; + // set constant values + this.defaultOptions = { + nodes: { + customScalingFunction: customScalingFunction, + mass: 1, + radiusMin: 10, + radiusMax: 30, + radius: 10, + shape: 'ellipse', + image: undefined, + widthMin: 16, // px + widthMax: 64, // px + fontColor: 'black', + fontSize: 14, // px + fontFace: 'verdana', + fontFill: undefined, + fontStrokeWidth: 0, // px + fontStrokeColor: '#ffffff', + fontDrawThreshold: 3, + scaleFontWithValue: false, + fontSizeMin: 14, + fontSizeMax: 30, + fontSizeMaxVisible: 30, + value: 1, + level: -1, + color: { + border: '#2B7CE9', + background: '#97C2FC', + highlight: { + border: '#2B7CE9', + background: '#D2E5FF' + }, + hover: { + border: '#2B7CE9', + background: '#D2E5FF' + } + }, + group: undefined, + borderWidth: 1, + borderWidthSelected: undefined + }, + edges: { + customScalingFunction: customScalingFunction, + widthMin: 1, // + widthMax: 15,// + width: 1, + widthSelectionMultiplier: 2, + hoverWidth: 1.5, + value:1, + style: 'line', + color: { + color:'#848484', + highlight:'#848484', + hover: '#848484' + }, + opacity:1.0, + fontColor: '#343434', + fontSize: 14, // px + fontFace: 'arial', + fontFill: 'white', + fontStrokeWidth: 0, // px + fontStrokeColor: 'white', + labelAlignment:'horizontal', + arrowScaleFactor: 1, + dash: { + length: 10, + gap: 5, + altLength: undefined + }, + inheritColor: "from", // to, from, false, true (== from) + useGradients: false // release in 4.0 + }, + configurePhysics:false, + physics: { + barnesHut: { + enabled: true, + thetaInverted: 1 / 0.5, // 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. - if (this.closeDiv === undefined) { - this.closeDiv = document.createElement('div'); - this.closeDiv.className = 'network-manipulation-closeDiv'; - this.closeDiv.style.display = this.manipulationDiv.style.display; - this.frame.appendChild(this.closeDiv); - } - // load the manipulation functions - this._loadMixin(ManipulationMixin); - // create the manipulator toolbar - this._createManipulatorBar(); - } - else { - if (this.manipulationDiv !== undefined) { - // removes all the bindings and overloads - this._createManipulatorBar(); - // remove the manipulation divs - this.frame.removeChild(this.manipulationDiv); - this.frame.removeChild(this.editModeDiv); - this.frame.removeChild(this.closeDiv); - this.manipulationDiv = undefined; - this.editModeDiv = undefined; - this.closeDiv = undefined; - // remove the mixin functions - this._clearMixin(ManipulationMixin); - } - } - }; + // + //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, // used for normalization of the cluster levels + //clusterByZoom: true // enable clustering through zooming in and out + }, + navigation: { + enabled: false + }, + keyboard: { + enabled: false, + speed: {x: 10, y: 10, zoom: 0.02}, + bindToWindow: true + }, + dataManipulation: { + enabled: false, + initiallyVisible: false + }, + hierarchicalLayout: { + enabled:false, + levelSeparation: 150, + nodeSpacing: 100, + direction: "UD", // UD, DU, LR, RL + layout: "hubsize" // hubsize, directed + }, + freezeForStabilization: false, + smoothCurves: { + enabled: true, + dynamic: true, + type: "continuous", + roundness: 0.5 + }, + maxVelocity: 50, + minVelocity: 0.1, // px/s + stabilize: true, // stabilize before displaying the network + stabilizationIterations: 1000, // maximum number of iteration to stabilize + zoomExtentOnStabilize: true, + locale: 'en', + locales: locales, + tooltip: { + delay: 300, + fontColor: 'black', + fontSize: 14, // px + fontFace: 'verdana', + color: { + border: '#666', + background: '#FFFFC6' + } + }, + dragNetwork: true, + dragNodes: true, + zoomable: true, + hover: false, + hideEdgesOnDrag: false, + hideNodesOnDrag: false, + width : '100%', + height : '100%', + selectable: true, + useDefaultGroups: true + }; + this.constants = util.extend({}, this.defaultOptions); + this.pixelRatio = 1; + + + this.hoverObj = {nodes:{},edges:{}}; + this.controlNodesActive = false; + this.navigationHammers = {existing:[], _new: []}; - /** - * Mixin the navigation (User Interface) system and initialize the parameters required - * - * @private - */ - exports._loadNavigationControls = function () { - this._loadMixin(NavigationMixin); - // the clean function removes the button divs, this is done to remove the bindings. - this._cleanNavigation(); - if (this.constants.navigation.enabled == true) { - this._loadNavigationElements(); - } - }; + // animation properties + this.animationSpeed = 1/this.renderRefreshRate; + this.animationEasingFunction = "easeInOutQuint"; + this.animating = false; + this.easingTime = 0; + this.sourceScale = 0; + this.targetScale = 0; + this.sourceTranslation = 0; + this.targetTranslation = 0; + this.lockedOnNodeId = null; + this.lockedOnNodeOffset = null; + this.touchTime = 0; + this.redrawRequested = false; + // Node variables + var network = this; + this.groups = new Groups(); // object with groups + this.images = new Images(); // object with images + this.images.setOnloadCallback(function (status) { + network._requestRedraw(); + }); - /** - * Mixin the hierarchical layout system. - * - * @private - */ - exports._loadHierarchySystem = function () { - this._loadMixin(HierarchicalLayoutMixin); - }; + // keyboard navigation variables + this.xIncrement = 0; + this.yIncrement = 0; + this.zoomIncrement = 0; + // 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(); -/***/ }, -/* 55 */ -/***/ function(module, exports, __webpack_require__) { - var keycharm = __webpack_require__(58); - var Emitter = __webpack_require__(56); - var Hammer = __webpack_require__(45); - var util = __webpack_require__(1); + // apply options + this._setTranslation(this.frame.clientWidth / 2, this.frame.clientHeight / 2); + this._setScale(1); + this.setOptions(options); - /** - * Turn an element into an clickToUse element. - * When not active, the element has a transparent overlay. When the overlay is - * clicked, the mode is changed to active. - * When active, the element is displayed with a blue border around it, and - * the interactive contents of the element can be used. When clicked outside - * the element, the elements mode is changed to inactive. - * @param {Element} container - * @constructor - */ - function Activator(container) { - this.active = false; + // other vars + this.freezeSimulationEnabled = false;// freeze the simulation + this.cachedFunctions = {}; + this.startedStabilization = false; + this.stabilized = false; + this.stabilizationIterations = null; + this.draggingNodes = false; - this.dom = { - container: container - }; + // 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 - this.dom.overlay = document.createElement('div'); - this.dom.overlay.className = 'overlay'; + // 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 - this.dom.container.appendChild(this.dom.overlay); + // datasets or dataviews + this.nodesData = null; // A DataSet or DataView + this.edgesData = null; // A DataSet or DataView - this.hammer = Hammer(this.dom.overlay, {prevent_default: false}); - this.hammer.on('tap', this._onTapOverlay.bind(this)); + // 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, params.data); + 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(); + } + }; - // block all touch events (except tap) - var me = this; - var events = [ - 'touch', 'pinch', - 'doubletap', 'hold', - 'dragstart', 'drag', 'dragend', - 'mousewheel', 'DOMMouseScroll' // DOMMouseScroll is needed for Firefox - ]; - events.forEach(function (event) { - me.hammer.on(event, function (event) { - event.stopPropagation(); - }); - }); + // properties for the animation + this.moving = true; + this.timer = undefined; // Scheduling function. Is definded in this.start(); - // attach a tap event to the window, in order to deactivate when clicking outside the timeline - this.windowHammer = Hammer(window, {prevent_default: false}); - this.windowHammer.on('tap', function (event) { - // deactivate when clicked outside the container - if (!_hasParent(event.target, container)) { - me.deactivate(); - } - }); + // 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); - if (this.keycharm !== undefined) { - this.keycharm.destroy(); + // hierarchical layout + this.initializing = false; + if (this.constants.hierarchicalLayout.enabled == true) { + this._setupHierarchicalLayout(); + } + else { + // zoom so all data will fit on the screen, if clustering is enabled, we do not want start to be called here. + if (this.constants.stabilize == false) { + this.zoomExtent({duration:0}, true, this.constants.clustering.enabled); + } } - this.keycharm = keycharm(); - // keycharm listener only bounded when active) - this.escListener = this.deactivate.bind(this); + // if clustering is disabled, the simulation will have started in the setData function + if (this.constants.clustering.enabled) { + this.startWithClustering(); + } } - // turn into an event emitter - Emitter(Activator.prototype); - - // The currently active activator - Activator.current = null; - - /** - * Destroy the activator. Cleans up all created DOM and event listeners - */ - Activator.prototype.destroy = function () { - this.deactivate(); - - // remove dom - this.dom.overlay.parentNode.removeChild(this.dom.overlay); - - // cleanup hammer instances - this.hammer = null; - this.windowHammer = null; - // FIXME: cleaning up hammer instances doesn't work (Timeline not removed from memory) - }; + // Extend Network with an Emitter mixin + Emitter(Network.prototype); /** - * Activate the element - * Overlay is hidden, element is decorated with a blue shadow border + * Determine if the browser requires a setTimeout or a requestAnimationFrame. This was required because + * some implementations (safari and IE9) did not support requestAnimationFrame + * @private */ - Activator.prototype.activate = function () { - // we allow only one active activator at a time - if (Activator.current) { - Activator.current.deactivate(); + Network.prototype._determineBrowserMethod = function() { + var browserType = navigator.userAgent.toLowerCase(); + this.requiresTimeout = false; + if (browserType.indexOf('msie 9.0') != -1) { // IE 9 + this.requiresTimeout = true; } - Activator.current = this; - - this.active = true; - this.dom.overlay.style.display = 'none'; - util.addClassName(this.dom.container, 'vis-active'); - - this.emit('change'); - this.emit('activate'); - - // ugly hack: bind ESC after emitting the events, as the Network rebinds all - // keyboard events on a 'change' event - this.keycharm.bind('esc', this.escListener); - }; - - /** - * Deactivate the element - * Overlay is displayed on top of the element - */ - Activator.prototype.deactivate = function () { - this.active = false; - this.dom.overlay.style.display = ''; - util.removeClassName(this.dom.container, 'vis-active'); - this.keycharm.unbind('esc', this.escListener); + else if (browserType.indexOf('safari') != -1) { // safari + if (browserType.indexOf('chrome') <= -1) { + this.requiresTimeout = true; + } + } + } - this.emit('change'); - this.emit('deactivate'); - }; /** - * Handle a tap event: activate the container - * @param event + * 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 */ - Activator.prototype._onTapOverlay = function (event) { - // activate the container - this.activate(); - event.stopPropagation(); - }; + Network.prototype._getScriptPath = function() { + var scripts = document.getElementsByTagName( 'script' ); - /** - * Test whether the element has the requested parent element somewhere in - * its chain of parent nodes. - * @param {HTMLElement} element - * @param {HTMLElement} parent - * @returns {boolean} Returns true when the parent is found somewhere in the - * chain of parent nodes. - * @private - */ - function _hasParent(element, parent) { - while (element) { - if (element === parent) { - return true + // 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); } - element = element.parentNode; } - return false; - } - - module.exports = Activator; + return null; + }; -/***/ }, -/* 56 */ -/***/ function(module, exports, __webpack_require__) { - /** - * Expose `Emitter`. - */ - - module.exports = Emitter; - - /** - * Initialize a new `Emitter`. - * - * @api public + * Find the center position of the network + * @private */ + Network.prototype._getRange = function(specificNodes) { + var minY = 1e9, maxY = -1e9, minX = 1e9, maxX = -1e9, node; + if (specificNodes.length > 0) { + for (var i = 0; i < specificNodes.length; i++) { + node = this.nodes[specificNodes[i]]; + if (minX > (node.boundingBox.left)) { + minX = node.boundingBox.left; + } + if (maxX < (node.boundingBox.right)) { + maxX = node.boundingBox.right; + } + if (minY > (node.boundingBox.bottom)) { + minY = node.boundingBox.top; + } // top is negative, bottom is positive + if (maxY < (node.boundingBox.top)) { + maxY = node.boundingBox.bottom; + } // top is negative, bottom is positive + } + } + else { + for (var nodeId in this.nodes) { + if (this.nodes.hasOwnProperty(nodeId)) { + node = this.nodes[nodeId]; + if (minX > (node.boundingBox.left)) { + minX = node.boundingBox.left; + } + if (maxX < (node.boundingBox.right)) { + maxX = node.boundingBox.right; + } + if (minY > (node.boundingBox.bottom)) { + minY = node.boundingBox.top; + } // top is negative, bottom is positive + if (maxY < (node.boundingBox.top)) { + maxY = node.boundingBox.bottom; + } // top is negative, bottom is positive + } + } + } - function Emitter(obj) { - if (obj) return mixin(obj); + 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}; }; - /** - * Mixin the emitter properties. - * - * @param {Object} obj - * @return {Object} - * @api private - */ - - function mixin(obj) { - for (var key in Emitter.prototype) { - obj[key] = Emitter.prototype[key]; - } - return obj; - } /** - * Listen on the given `event` with `fn`. - * - * @param {String} event - * @param {Function} fn - * @return {Emitter} - * @api public + * @param {object} range = {minX: minX, maxX: maxX, minY: minY, maxY: maxY}; + * @returns {{x: number, y: number}} + * @private */ - - Emitter.prototype.on = - Emitter.prototype.addEventListener = function(event, fn){ - this._callbacks = this._callbacks || {}; - (this._callbacks[event] = this._callbacks[event] || []) - .push(fn); - return this; + Network.prototype._findCenter = function(range) { + return {x: (0.5 * (range.maxX + range.minX)), + y: (0.5 * (range.maxY + range.minY))}; }; + /** - * Adds an `event` listener that will be invoked a single - * time then automatically removed. + * This function zooms out to fit all data on screen based on amount of nodes * - * @param {String} event - * @param {Function} fn - * @return {Emitter} - * @api public + * @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(options, initialZoom, disableStart) { + this._redraw(true); - Emitter.prototype.once = function(event, fn){ - var self = this; - this._callbacks = this._callbacks || {}; - - function on() { - self.off(event, on); - fn.apply(this, arguments); + if (initialZoom === undefined) {initialZoom = false;} + if (disableStart === undefined) {disableStart = false;} + if (options === undefined) {options = {nodes:[]};} + if (options.nodes === undefined) { + options.nodes = []; } - on.fn = fn; - this.on(event, on); - return this; - }; - - /** - * Remove the given callback for `event` or all - * registered callbacks. - * - * @param {String} event - * @param {Function} fn - * @return {Emitter} - * @api public - */ + var range; + var zoomLevel; - Emitter.prototype.off = - Emitter.prototype.removeListener = - Emitter.prototype.removeAllListeners = - Emitter.prototype.removeEventListener = function(event, fn){ - this._callbacks = this._callbacks || {}; + if (initialZoom == true) { + // check if more than half of the nodes have a predefined position. If so, we use the range, not the approximation. + var positionDefined = 0; + for (var nodeId in this.nodes) { + if (this.nodes.hasOwnProperty(nodeId)) { + var node = this.nodes[nodeId]; + if (node.predefinedPosition == true) { + positionDefined += 1; + } + } + } + if (positionDefined > 0.5 * this.nodeIndices.length) { + this.zoomExtent(options,false,disableStart); + return; + } - // all - if (0 == arguments.length) { - this._callbacks = {}; - return this; - } + range = this._getRange(options.nodes); - // specific event - var callbacks = this._callbacks[event]; - if (!callbacks) return this; + 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. + } + } - // remove all handlers - if (1 == arguments.length) { - delete this._callbacks[event]; - return this; + // correct for larger canvasses. + var factor = Math.min(this.frame.canvas.clientWidth / 600, this.frame.canvas.clientHeight / 600); + zoomLevel *= factor; } + else { + range = this._getRange(options.nodes); + var xDistance = Math.abs(range.maxX - range.minX) * 1.1; + var yDistance = Math.abs(range.maxY - range.minY) * 1.1; - // 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; - } + var xZoomLevel = this.frame.canvas.clientWidth / xDistance; + var yZoomLevel = this.frame.canvas.clientHeight / yDistance; + zoomLevel = (xZoomLevel <= yZoomLevel) ? xZoomLevel : yZoomLevel; } - return this; - }; - /** - * Emit `event` with the given args. - * - * @param {String} event - * @param {Mixed} ... - * @return {Emitter} - */ + if (zoomLevel > 1.0) { + zoomLevel = 1.0; + } - Emitter.prototype.emit = function(event){ - this._callbacks = this._callbacks || {}; - var args = [].slice.call(arguments, 1) - , callbacks = this._callbacks[event]; - if (callbacks) { - callbacks = callbacks.slice(0); - for (var i = 0, len = callbacks.length; i < len; ++i) { - callbacks[i].apply(this, args); - } + var center = this._findCenter(range); + if (disableStart == false) { + var options = {position: center, scale: zoomLevel, animation: options}; + this.moveTo(options); + this.moving = true; + this.start(); + } + else { + center.x *= zoomLevel; + center.y *= zoomLevel; + center.x -= 0.5 * this.frame.canvas.clientWidth; + center.y -= 0.5 * this.frame.canvas.clientHeight; + this._setScale(zoomLevel); + this._setTranslation(-center.x,-center.y); } - - return this; }; + /** - * Return array of callbacks for `event`. - * - * @param {String} event - * @return {Array} - * @api public + * Update the this.nodeIndices with the most recent node index list + * @private */ - - Emitter.prototype.listeners = function(event){ - this._callbacks = this._callbacks || {}; - return this._callbacks[event] || []; + Network.prototype._updateNodeIndexList = function() { + this._clearNodeIndexList(); + this.nodeIndices = Object.keys(this.nodes); }; + /** - * Check if this emitter has `event` handlers. + * Set nodes and edges, and optionally options as well. * - * @param {String} event - * @return {Boolean} - * @api public + * @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; + } - Emitter.prototype.hasListeners = function(event){ - return !! this.listeners(event).length; - }; - - -/***/ }, -/* 57 */ -/***/ function(module, exports, __webpack_require__) { + // unselect all to ensure no selections from old data are carried over. + this._unselectAll(true); - 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 */ + // we set initializing to true to ensure that the hierarchical layout is not performed until both nodes and edges are added. + this.initializing = true; - (function(window, undefined) { - 'use strict'; + 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.'); + } - /** - * @main - * @module hammer - * - * @class Hammer - * @static - */ + // clean up in case there is anyone in an active mode of the manipulation. This is the same option as bound to the escape button. + if (this.constants.dataManipulation.enabled == true) { + this._createManipulatorBar(); + } - /** - * 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 || {}); + // 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; + } + } + else if (data && data.gephi) { + // parse DOT file + if(data && data.gephi) { + var gephiData = gephiParser.parseGephi(data.gephi); + this.setData(gephiData); + return; + } + } + else { + this._setNodes(data && data.nodes); + this._setEdges(data && data.edges); + } + this._putDataInSector(); + if (disableStart == false) { + if (this.constants.hierarchicalLayout.enabled == true) { + this._resetLevels(); + this._setupHierarchicalLayout(); + } + else { + // find a stable position or start animating to a stable position + if (this.constants.stabilize == true) { + this._stabilize(); + } + } + this.start(); + } + this.initializing = false; }; /** - * version, as defined in package.json - * the value will be set at each build - * @property VERSION - * @final - * @type {String} + * Set options + * @param {Object} options */ - Hammer.VERSION = '1.1.3'; + Network.prototype.setOptions = function (options) { + if (options) { + var prop; + var fields = ['nodes','edges','smoothCurves','hierarchicalLayout','clustering','navigation', + 'keyboard','dataManipulation','onAdd','onEdit','onEditEdge','onConnect','onDelete','clickToUse' + ]; + // extend all but the values in fields + util.selectiveNotDeepExtend(fields,this.constants, options); + util.selectiveNotDeepExtend(['color'],this.constants.nodes, options.nodes); + util.selectiveNotDeepExtend(['color','length'],this.constants.edges, options.edges); - /** - * 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', + this.groups.useDefaultGroups = this.constants.useDefaultGroups; + if (options.physics) { + util.mergeOptions(this.constants.physics, options.physics,'barnesHut'); + util.mergeOptions(this.constants.physics, options.physics,'repulsion'); - /** - * 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', + 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]; + } + } + } + } - /** - * 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 (options.onAdd) {this.triggerFunctions.add = options.onAdd;} + if (options.onEdit) {this.triggerFunctions.edit = options.onEdit;} + if (options.onEditEdge) {this.triggerFunctions.editEdge = options.onEditEdge;} + if (options.onConnect) {this.triggerFunctions.connect = options.onConnect;} + if (options.onDelete) {this.triggerFunctions.del = options.onDelete;} - /** - * Specifies whether zooming is enabled. Used by IE10> - * @property defaults.behavior.contentZooming - * @type {String} - * @default 'none' - */ - contentZooming: 'none', + util.mergeOptions(this.constants, options,'smoothCurves'); + util.mergeOptions(this.constants, options,'hierarchicalLayout'); + util.mergeOptions(this.constants, options,'clustering'); + util.mergeOptions(this.constants, options,'navigation'); + util.mergeOptions(this.constants, options,'keyboard'); + util.mergeOptions(this.constants, options,'dataManipulation'); - /** - * 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)' + if (options.dataManipulation) { + this.editMode = this.constants.dataManipulation.initiallyVisible; } - }; - /** - * 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; + // TODO: work out these options and document them + if (options.edges) { + if (options.edges.color !== undefined) { + if (util.isString(options.edges.color)) { + this.constants.edges.color = {}; + this.constants.edges.color.color = options.edges.color; + this.constants.edges.color.highlight = options.edges.color; + this.constants.edges.color.hover = options.edges.color; + } + else { + if (options.edges.color.color !== undefined) {this.constants.edges.color.color = options.edges.color.color;} + if (options.edges.color.highlight !== undefined) {this.constants.edges.color.highlight = options.edges.color.highlight;} + if (options.edges.color.hover !== undefined) {this.constants.edges.color.hover = options.edges.color.hover;} + } + this.constants.edges.inheritColor = false; + } - /** - * detect support for touch events - * @property HAS_TOUCHEVENTS - * @type {Boolean} - */ - Hammer.HAS_TOUCHEVENTS = ('ontouchstart' in window); + 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;} + } + } + } - /** - * detect mobile browsers - * @property IS_MOBILE - * @type {Boolean} - */ - Hammer.IS_MOBILE = /mobile|tablet|ip(ad|hone|od)|android|silk/i.test(navigator.userAgent); + if (options.nodes) { + if (options.nodes.color) { + var newColorObj = util.parseColor(options.nodes.color); + this.constants.nodes.color.background = newColorObj.background; + this.constants.nodes.color.border = newColorObj.border; + this.constants.nodes.color.highlight.background = newColorObj.highlight.background; + this.constants.nodes.color.highlight.border = newColorObj.highlight.border; + this.constants.nodes.color.hover.background = newColorObj.hover.background; + this.constants.nodes.color.hover.border = newColorObj.hover.border; + } + } + if (options.groups) { + for (var groupname in options.groups) { + if (options.groups.hasOwnProperty(groupname)) { + var group = options.groups[groupname]; + this.groups.add(groupname, group); + } + } + } + + 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); + } + } + + if ('clickToUse' in options) { + if (options.clickToUse) { + if (!this.activator) { + this.activator = new Activator(this.frame); + this.activator.on('change', this._createKeyBinds.bind(this)); + } + } + else { + if (this.activator) { + this.activator.destroy(); + delete this.activator; + } + } + } + + if (options.labels) { + throw new Error('Option "labels" is deprecated. Use options "locale" and "locales" instead.'); + } + + + // (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 hammer + this._bindHammer(); + + // bind keys. If disabled, this will not do anything; + this._createKeyBinds(); + + this._markAllEdgesAsDirty(); + this.setSize(this.constants.width, this.constants.height); + this.moving = true; + if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { + this._resetLevels(); + this._setupHierarchicalLayout(); + } + this.start(); + } + }; - /** - * 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 + * 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 - * @writeOnce - * @type {Object} */ - var EVENT_TYPES = {}; + 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 = 'vis network-frame'; + this.frame.style.position = 'relative'; + this.frame.style.overflow = 'hidden'; + this.frame.tabIndex = 900; + + + ////////////////////////////////////////////////////////////////// + + 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); + } + else { + var ctx = this.frame.canvas.getContext("2d"); + this.pixelRatio = (window.devicePixelRatio || 1) / (ctx.webkitBackingStorePixelRatio || + ctx.mozBackingStorePixelRatio || + ctx.msBackingStorePixelRatio || + ctx.oBackingStorePixelRatio || + ctx.backingStorePixelRatio || 1); + + //this.pixelRatio = Math.max(1,this.pixelRatio); // this is to account for browser zooming out. The pixel ratio is ment to switch between 1 and 2 for HD screens. + this.frame.canvas.getContext("2d").setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0); + } + + this._bindHammer(); + }; + /** - * direction strings, for safe comparisons - * @property DIRECTION_DOWN|LEFT|UP|RIGHT - * @final - * @type {String} - * @default 'down' 'left' 'up' 'right' + * This function binds hammer, it can be repeated over and over due to the uniqueness check. + * @private */ - 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'; + Network.prototype._bindHammer = function() { + var me = this; + if (this.hammer !== undefined) { + this.hammer.dispose(); + } + 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('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) ); + + if (this.constants.zoomable == true) { + this.hammer.on('mousewheel', me._onMouseWheel.bind(me)); + this.hammer.on('DOMMouseScroll', me._onMouseWheel.bind(me)); // for FF + this.hammer.on('pinch', me._onPinch.bind(me) ); + } + + this.hammer.on('mousemove', me._onMouseMoveTitle.bind(me) ); + + this.hammerFrame = Hammer(this.frame, { + prevent_default: true + }); + this.hammerFrame.on('release', me._onRelease.bind(me) ); + + // add the frame to the container element + this.containerElement.appendChild(this.frame); + } /** - * pointertype strings, for safe comparisons - * @property POINTER_MOUSE|TOUCH|PEN - * @final - * @type {String} - * @default 'mouse' 'touch' 'pen' + * Binding the keys for keyboard navigation. These functions are defined in the NavigationMixin + * @private */ - var POINTER_MOUSE = Hammer.POINTER_MOUSE = 'mouse'; - var POINTER_TOUCH = Hammer.POINTER_TOUCH = 'touch'; - var POINTER_PEN = Hammer.POINTER_PEN = 'pen'; + Network.prototype._createKeyBinds = function() { + var me = this; + if (this.keycharm !== undefined) { + this.keycharm.destroy(); + } + + if (this.constants.keyboard.bindToWindow == true) { + this.keycharm = keycharm({container: window, preventDefault: false}); + } + else { + this.keycharm = keycharm({container: this.frame, preventDefault: false}); + } + + this.keycharm.reset(); + + if (this.constants.keyboard.enabled && this.isActive()) { + this.keycharm.bind("up", this._moveUp.bind(me) , "keydown"); + this.keycharm.bind("up", this._yStopMoving.bind(me), "keyup"); + this.keycharm.bind("down", this._moveDown.bind(me) , "keydown"); + this.keycharm.bind("down", this._yStopMoving.bind(me), "keyup"); + this.keycharm.bind("left", this._moveLeft.bind(me) , "keydown"); + this.keycharm.bind("left", this._xStopMoving.bind(me), "keyup"); + this.keycharm.bind("right",this._moveRight.bind(me), "keydown"); + this.keycharm.bind("right",this._xStopMoving.bind(me), "keyup"); + this.keycharm.bind("=", this._zoomIn.bind(me), "keydown"); + this.keycharm.bind("=", this._stopZoom.bind(me), "keyup"); + this.keycharm.bind("num+", this._zoomIn.bind(me), "keydown"); + this.keycharm.bind("num+", this._stopZoom.bind(me), "keyup"); + this.keycharm.bind("num-", this._zoomOut.bind(me), "keydown"); + this.keycharm.bind("num-", this._stopZoom.bind(me), "keyup"); + this.keycharm.bind("-", this._zoomOut.bind(me), "keydown"); + this.keycharm.bind("-", this._stopZoom.bind(me), "keyup"); + this.keycharm.bind("[", this._zoomIn.bind(me), "keydown"); + this.keycharm.bind("[", this._stopZoom.bind(me), "keyup"); + this.keycharm.bind("]", this._zoomOut.bind(me), "keydown"); + this.keycharm.bind("]", this._stopZoom.bind(me), "keyup"); + this.keycharm.bind("pageup",this._zoomIn.bind(me), "keydown"); + this.keycharm.bind("pageup",this._stopZoom.bind(me), "keyup"); + this.keycharm.bind("pagedown",this._zoomOut.bind(me),"keydown"); + this.keycharm.bind("pagedown",this._stopZoom.bind(me), "keyup"); + } + + if (this.constants.dataManipulation.enabled == true) { + this.keycharm.bind("esc",this._createManipulatorBar.bind(me)); + this.keycharm.bind("delete",this._deleteSelected.bind(me)); + } + }; /** - * eventtypes - * @property EVENT_START|MOVE|END|RELEASE|TOUCH - * @final - * @type {String} - * @default 'start' 'change' 'move' 'end' 'release' 'touch' + * Cleans up all bindings of the network, removing it fully from the memory IF the variable is set to null after calling this function. + * var network = new vis.Network(..); + * network.destroy(); + * network = null; */ - 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'; + Network.prototype.destroy = function() { + this.start = function () {}; + this.redraw = function () {}; + this.timer = false; + + // cleanup physicsConfiguration if it exists + this._cleanupPhysicsConfiguration(); + + // remove keybindings + this.keycharm.reset(); + + // clear hammer bindings + this.hammer.dispose(); + + // clear events + this.off(); + + this._recursiveDOMDelete(this.containerElement); + } + + Network.prototype._recursiveDOMDelete = function(DOMobject) { + while (DOMobject.hasChildNodes() == true) { + this._recursiveDOMDelete(DOMobject.firstChild); + DOMobject.removeChild(DOMobject.firstChild); + } + } /** - * if the window events are set... - * @property READY - * @writeOnce - * @type {Boolean} - * @default false + * Get the pointer location from a touch location + * @param {{pageX: Number, pageY: Number}} touch + * @return {{x: Number, y: Number}} pointer + * @private */ - Hammer.READY = false; + Network.prototype._getPointer = function (touch) { + return { + x: touch.pageX - util.getAbsoluteLeft(this.frame.canvas), + y: touch.pageY - util.getAbsoluteTop(this.frame.canvas) + }; + }; /** - * plugins namespace - * @property plugins - * @type {Object} + * On start of a touch gesture, store the pointer + * @param event + * @private */ - Hammer.plugins = Hammer.plugins || {}; + Network.prototype._onTouch = function (event) { + if (new Date().valueOf() - this.touchTime > 100) { + this.drag.pointer = this._getPointer(event.gesture.center); + this.drag.pinched = false; + this.pinch.scale = this._getScale(); + + // to avoid double fireing of this event because we have two hammer instances. (on canvas and on frame) + this.touchTime = new Date().valueOf(); + + this._handleTouch(this.drag.pointer); + } + }; /** - * gestures namespace - * see `/gestures` for the definitions - * @property gestures - * @type {Object} + * handle drag start event + * @private */ - Hammer.gestures = Hammer.gestures || {}; + Network.prototype._onDragStart = function (event) { + this._handleDragStart(event); + }; + /** - * setup events to detect gestures on the document - * this function is called when creating an new instance + * This function is called by _onDragStart. + * It is separated out because we can then overload it for the datamanipulation system. + * * @private */ - function setup() { - if(Hammer.READY) { - return; + Network.prototype._handleDragStart = function(event) { + // in case the touch event was triggered on an external div, do the initial touch now. + if (this.drag.pointer === undefined) { + this._onTouch(event); + } + + var node = this._getNodeAt(this.drag.pointer); + // note: drag.pointer is set in _onTouch to get the initial touch location + + this.drag.dragging = true; + this.drag.selection = []; + this.drag.translation = this._getTranslation(); + this.drag.nodeId = null; + this.draggingNodes = false; + + if (node != null && this.constants.dragNodes == true) { + this.draggingNodes = true; + this.drag.nodeId = node.id; + // select the clicked node if not yet selected + if (!node.isSelected()) { + this._selectObject(node,false); } - // find what eventtypes we add listeners to - Event.determineEventTypes(); + this.emit("dragStart",{nodeIds:this.getSelection().nodes}); - // Register all gestures inside Hammer.gestures - Utils.each(Hammer.gestures, function(gesture) { - Detection.register(gesture); - }); + // 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, - // Add touch events on the document - Event.onTouch(Hammer.DOCUMENT, EVENT_MOVE, Detection.detect); - Event.onTouch(Hammer.DOCUMENT, EVENT_END, Detection.detect); + // 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; + + this.drag.selection.push(s); + } + } + } + }; - // Hammer is ready...! - Hammer.READY = true; - } /** - * @module hammer - * - * @class Utils - * @static + * handle drag event + * @private */ - 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; - }, + Network.prototype._onDrag = function (event) { + this._handleOnDrag(event) + }; - /** - * 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); - }, + /** + * 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; + } - /** - * 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; + // remove the focus on node if it is focussed on by the focusOnNode + this.releaseNode(); - // 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; - } - } - } - }, + var pointer = this._getPointer(event.gesture.center); + 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; - /** - * 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; - }, + // update position of all selected nodes + selection.forEach(function (s) { + var node = s.node; - /** - * 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; - } - }, + if (!s.xFixed) { + node.x = me._XconvertDOMtoCanvas(me._XconvertCanvasToDOM(s.x) + deltaX); + } - /** - * 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); - }, + if (!s.yFixed) { + node.y = me._YconvertDOMtoCanvas(me._YconvertCanvasToDOM(s.y) + deltaY); + } + }); - /** - * 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; + // start _animationStep if not yet running + if (!this.moving) { + this.moving = true; + this.start(); + } + } + else { + // move the network + if (this.constants.dragNetwork == true) { + // if the drag was not started properly because the click started outside the network div, start it now. + if (this.drag.pointer === undefined) { + this._handleDragStart(event); + return; + } + var diffX = pointer.x - this.drag.pointer.x; + var diffY = pointer.y - this.drag.pointer.y; - // 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 - }; - } + this._setTranslation( + this.drag.translation.x + diffX, + this.drag.translation.y + diffY + ); + this._redraw(); + } + } + }; - Utils.each(touches, function(touch) { - pageX.push(touch.pageX); - pageY.push(touch.pageY); - clientX.push(touch.clientX); - clientY.push(touch.clientY); - }); + /** + * handle drag start event + * @private + */ + Network.prototype._onDragEnd = function (event) { + this._handleDragEnd(event); + }; - 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 - }; - }, + Network.prototype._handleDragEnd = function(event) { + 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(); + } + if (this.draggingNodes == false) { + this.emit("dragEnd",{nodeIds:[]}); + } + else { + this.emit("dragEnd",{nodeIds:this.getSelection().nodes}); + } - /** - * 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; + } + /** + * 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); - 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; - }, + /** + * handle doubletap event + * @private + */ + Network.prototype._onDoubleTap = function (event) { + var pointer = this._getPointer(event.gesture.center); + this._handleDoubleTap(pointer); + }; - /** - * 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)); - }, + /** + * 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); + }; - /** - * 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; - }, + /** + * handle the release of the screen + * + * @private + */ + Network.prototype._onRelease = function (event) { + var pointer = this._getPointer(event.gesture.center); + this._handleOnRelease(pointer); + }; - /** - * 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; - }, + /** + * Handle pinch event + * @param event + * @private + */ + Network.prototype._onPinch = function (event) { + var pointer = this._getPointer(event.gesture.center); - /** - * find out if the direction is vertical * - * @method isVertical - * @param {String} direction matches `DIRECTION_UP|DOWN` - * @return {Boolean} is_vertical - */ - isVertical: function isVertical(direction) { - return direction == DIRECTION_UP || direction == DIRECTION_DOWN; - }, + this.drag.pinched = true; + if (!('scale' in this.pinch)) { + this.pinch.scale = 1; + } - /** - * 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); + // TODO: enabled moving while pinching? + var scale = this.pinch.scale * event.gesture.scale; + this._zoom(scale, pointer) + }; - 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); - } + /** + * Zoom the network in or out + * @param {Number} scale a number around 1, and between 0.01 and 10 + * @param {{x: Number, y: Number}} pointer Position on screen + * @return {Number} appliedScale scale is limited within the boundaries + * @private + */ + Network.prototype._zoom = function(scale, pointer) { + if (this.constants.zoomable == true) { + var scaleOld = this._getScale(); + if (scale < 0.00001) { + scale = 0.00001; + } + if (scale > 10) { + scale = 10; + } - // test the style - if(p in element.style) { - element.style[p] = (toggle == null || toggle) && value || ''; - break; - } - } - }, + 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(); - /** - * 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; - } + var scaleFrac = scale / scaleOld; + var tx = (1 - scaleFrac) * pointer.x + translation.x * scaleFrac; + var ty = (1 - scaleFrac) * pointer.y + translation.y * scaleFrac; - // set the css properties - Utils.each(props, function(value, prop) { - Utils.setPrefixedCss(element, prop, value, toggle); - }); + this.areaCenter = {"x" : this._XconvertDOMtoCanvas(pointer.x), + "y" : this._YconvertDOMtoCanvas(pointer.y)}; - var falseFn = toggle && function() { - return false; - }; + this._setScale(scale); + this._setTranslation(tx, ty); - // also the disable onselectstart - if(props.userSelect == 'none') { - element.onselectstart = falseFn; - } - // and disable ondragstart - if(props.userDrag == 'none') { - element.ondragstart = falseFn; - } - }, + if (preScaleDragPointer != null) { + var postScaleDragPointer = this.canvasToDOM(preScaleDragPointer); + this.drag.pointer.x = postScaleDragPointer.x; + this.drag.pointer.y = postScaleDragPointer.y; + } - /** - * 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(); - }); + this._redraw(); + + if (scaleOld < scale) { + this.emit("zoom", {direction:"+"}); } + else { + this.emit("zoom", {direction:"-"}); + } + + return scale; + } }; /** - * @module hammer - */ - /** - * @class Event - * @static + * 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 */ - 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, + 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; + } - /** - * when the mouse is hold down, this is true - * @property should_detect - * @private - * @type {Boolean} - */ - shouldDetect: false, + // 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) { - /** - * 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); - }); - }, + // calculate the new scale + var scale = this._getScale(); + var zoom = delta / 10; + if (delta < 0) { + zoom = zoom / (1 - zoom); + } + scale *= (1 + zoom); - /** - * 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); - }); - }, + // calculate the pointer location + var gesture = hammerUtil.fakeGesture(this, event); + var pointer = this._getPointer(gesture.center); - /** - * 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; + // apply the new scale + this._zoom(scale, pointer); + } - var onTouchHandler = function onTouchHandler(ev) { - var srcType = ev.type.toLowerCase(), - isPointer = Hammer.HAS_POINTEREVENTS, - isMouse = Utils.inStr(srcType, 'mouse'), - triggerType; + // Prevent default actions caused by mouse wheel. + event.preventDefault(); + }; - // 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); - } + /** + * Mouse move handler for checking whether the title moves over a node with a title. + * @param {Event} event + * @private + */ + Network.prototype._onMouseMoveTitle = function (event) { + var gesture = hammerUtil.fakeGesture(this, event); + var pointer = this._getPointer(gesture.center); + var popupVisible = false; - // ...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 - } + // check if the previously selected node is still selected + if (this.popup !== undefined) { + if (this.popup.hidden === false) { + this._checkHidePopup(pointer); + } - if(isPointer && eventType == EVENT_END) { - PointerEvent.updatePointer(eventType, ev); - } - }; + // if the popup was not hidden above + if (this.popup.hidden === false) { + popupVisible = true; + this.popup.setPosition(pointer.x + 3,pointer.y - 5) + this.popup.show(); + } + } - this.on(element, EVENT_TYPES[eventType], onTouchHandler); - return onTouchHandler; - }, + // if we bind the keyboard to the div, we have to highlight it to use it. This highlights it on mouse over + if (this.constants.keyboard.bindToWindow == false && this.constants.keyboard.enabled == true) { + this.frame.focus(); + } - /** - * 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; + // start a timeout that will check if the mouse is positioned above an element + if (popupVisible === false) { + 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); + } + } - // 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; + /** + * 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]; + } + } - // keep track of how many touches have been removed - changedLength = touchList.length - ((ev.changedTouches) ? ev.changedTouches.length : 1); - } + // adding hover highlights + var obj = this._getNodeAt(pointer); + if (obj == null) { + obj = this._getEdgeAt(pointer); + } + if (obj != null) { + this._hoverObject(obj); + } - // 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; + // removing all node hover highlights except for the selected one. + for (var nodeId in this.hoverObj.nodes) { + if (this.hoverObj.nodes.hasOwnProperty(nodeId)) { + if (obj instanceof Node && obj.id != nodeId || obj instanceof Edge || obj == null) { + this._blurObject(this.hoverObj.nodes[nodeId]); + delete this.hoverObj.nodes[nodeId]; } + } + } + this.redraw(); + } + }; - // detection has been started, we keep track of this, see above - this.started = true; + /** + * 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) + }; - // generate some event data, some basic information - var evData = this.collectEventData(element, triggerType, touchList, ev); + var id; + var previousPopupObjId = this.popupObj === undefined ? "" : this.popupObj.id; + var nodeUnderCursor = false; + var popupType = "node"; - // 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); + if (this.popupObj == undefined) { + // search the nodes for overlap, select the top one in case of multiple nodes + var nodes = this.nodes; + var overlappingNodes = []; + for (id in nodes) { + if (nodes.hasOwnProperty(id)) { + var node = nodes[id]; + if (node.isOverlappingWith(obj)) { + if (node.getTitle() !== undefined) { + overlappingNodes.push(id); + } } + } + } - // 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); + if (overlappingNodes.length > 0) { + // if there are overlapping nodes, select the last one, this is the + // one which is drawn on top of the others + this.popupObj = this.nodes[overlappingNodes[overlappingNodes.length - 1]]; + // if you hover over a node, the title of the edge is not supposed to be shown. + nodeUnderCursor = true; + } + } - evData.eventType = triggerType; - delete evData.changedLength; + if (this.popupObj === undefined && nodeUnderCursor == false) { + // search the edges for overlap + var edges = this.edges; + var overlappingEdges = []; + for (id in edges) { + if (edges.hasOwnProperty(id)) { + var edge = edges[id]; + if (edge.connected === true && (edge.getTitle() !== undefined) && + edge.isOverlappingWith(obj)) { + overlappingEdges.push(id); } + } + } - // trigger the END event - if(triggerType == EVENT_END) { - handler.call(Detection, evData); + if (overlappingEdges.length > 0) { + this.popupObj = this.edges[overlappingEdges[overlappingEdges.length - 1]]; + popupType = "edge"; + } + } - // ...and we are done with the detection - // so reset everything to start each detection totally fresh - this.started = false; - } + if (this.popupObj) { + // show popup message window + if (this.popupObj.id != previousPopupObjId) { + if (this.popup === undefined) { + this.popup = new Popup(this.frame, this.constants.tooltip); + } - return triggerType; - }, + this.popup.popupTargetType = popupType; + this.popup.popupTargetId = this.popupObj.id; - /** - * 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' - ]; - } + // 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 + this.popup.setPosition(pointer.x + 3, pointer.y - 5); + this.popup.setText(this.popupObj.getTitle()); + this.popup.show(); + } + } + else { + if (this.popup) { + this.popup.hide(); + } + } + }; - 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(); - } + /** + * Check if the popup must be hidden, 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) { + var pointerObj = { + left: this._XconvertDOMtoCanvas(pointer.x), + top: this._YconvertDOMtoCanvas(pointer.y), + right: this._XconvertDOMtoCanvas(pointer.x), + bottom: this._YconvertDOMtoCanvas(pointer.y) + }; - // get the touchlist - if(ev.touches) { - if(eventType == EVENT_MOVE) { - return ev.touches; - } + var stillOnObj = false; + if (this.popup.popupTargetType == 'node') { + stillOnObj = this.nodes[this.popup.popupTargetId].isOverlappingWith(pointerObj); + if (stillOnObj === true) { + var overNode = this._getNodeAt(pointer); + stillOnObj = overNode.id == this.popup.popupTargetId; + } + } + else { + if (this._getNodeAt(pointer) === null) { + stillOnObj = this.edges[this.popup.popupTargetId].isOverlappingWith(pointerObj); + } + } - 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); - }); + if (stillOnObj === false) { + this.popupObj = undefined; + this.popup.hide(); + } + }; - return touchList; - } - // make fake touchList from mouse position - ev.identifier = 1; - return [ev]; - }, + /** + * 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) { + var emitEvent = false; + var oldWidth = this.frame.canvas.width; + var oldHeight = this.frame.canvas.height; + if (width != this.constants.width || height != this.constants.height || this.frame.style.width != width || this.frame.style.height != height) { + this.frame.style.width = width; + this.frame.style.height = height; - /** - * 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; - } + this.frame.canvas.style.width = '100%'; + this.frame.canvas.style.height = '100%'; - return { - center: Utils.getCenter(touches), - timeStamp: Date.now(), - target: ev.target, - touches: touches, - eventType: eventType, - pointerType: pointerType, - srcEvent: ev, + this.frame.canvas.width = this.frame.canvas.clientWidth * this.pixelRatio; + this.frame.canvas.height = this.frame.canvas.clientHeight * this.pixelRatio; - /** - * 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(); - }, + this.constants.width = width; + this.constants.height = height; - /** - * stop bubbling the event up to its parents - */ - stopPropagation: function() { - this.srcEvent.stopPropagation(); - }, + emitEvent = true; + } + else { + // this would adapt the width of the canvas to the width from 100% if and only if + // there is a change. - /** - * immediately stop gesture detection - * might be useful after a swipe was detected - * @return {*} - */ - stopDetect: function() { - return Detection.stopDetect(); - } - }; + if (this.frame.canvas.width != this.frame.canvas.clientWidth * this.pixelRatio) { + this.frame.canvas.width = this.frame.canvas.clientWidth * this.pixelRatio; + emitEvent = true; } - }; + if (this.frame.canvas.height != this.frame.canvas.clientHeight * this.pixelRatio) { + this.frame.canvas.height = this.frame.canvas.clientHeight * this.pixelRatio; + emitEvent = true; + } + } + if (emitEvent == true) { + this.emit('resize', {width:this.frame.canvas.width * this.pixelRatio,height:this.frame.canvas.height * this.pixelRatio, oldWidth: oldWidth * this.pixelRatio, oldHeight: oldHeight * this.pixelRatio}); + } + }; /** - * @module hammer - * - * @class PointerEvent - * @static + * Set a data set with nodes for the network + * @param {Array | DataSet | DataView} nodes The data containing the nodes. + * @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; - }, + Network.prototype._setNodes = function(nodes) { + var oldNodesData = this.nodesData; - /** - * 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; - } - }, + if (nodes instanceof DataSet || nodes instanceof DataView) { + this.nodesData = nodes; + } + else if (Array.isArray(nodes)) { + this.nodesData = new DataSet(); + this.nodesData.add(nodes); + } + else if (!nodes) { + this.nodesData = new DataSet(); + } + else { + throw new TypeError('Array or DataSet expected'); + } - /** - * 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 (oldNodesData) { + // unsubscribe from old dataset + util.forEach(this.nodesListeners, function (callback, event) { + oldNodesData.off(event, callback); + }); + } - var pt = ev.pointerType, - types = {}; + // remove drawn nodes + this.nodes = {}; - 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 (this.nodesData) { + // subscribe to new dataset + var me = this; + util.forEach(this.nodesListeners, function (callback, event) { + me.nodesData.on(event, callback); + }); - /** - * reset the stored pointers - * @method reset - */ - reset: function resetList() { - this.pointers = {}; - } + // draw all new nodes + var ids = this.nodesData.getIds(); + this._addNodes(ids); + } + this._updateSelection(); }; - /** - * @module hammer - * - * @class Detection - * @static + * Add nodes + * @param {Number[] | String[]} ids + * @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, - - // 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, + Network.prototype._addNodes = function(ids) { + var id; + for (var i = 0, len = ids.length; i < len; i++) { + id = ids[i]; + var data = this.nodesData.get(id); + var node = new Node(data, this.images, this.groups, this.constants); + this.nodes[id] = node; // note: this may replace an existing node + if ((node.xFixed == false || node.yFixed == false) && (node.x === null || node.y === null)) { + var radius = 10 * 0.1*ids.length + 10; + var angle = 2 * Math.PI * Math.random(); + if (node.xFixed == false) {node.x = radius * Math.cos(angle);} + if (node.yFixed == false) {node.y = radius * Math.sin(angle);} + } + this.moving = true; + } - /** - * 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._updateNodeIndexList(); + if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { + this._resetLevels(); + this._setupHierarchicalLayout(); + } + this._updateCalculationNodes(); + this._reconnectEdges(); + this._updateValueRange(this.nodes); + }; - this.stopped = false; + /** + * Update existing nodes, or create them when not yet existing + * @param {Number[] | String[]} ids + * @private + */ + Network.prototype._updateNodes = function(ids,changedData) { + var nodes = this.nodes; + for (var i = 0, len = ids.length; i < len; i++) { + var id = ids[i]; + var node = nodes[id]; + var data = changedData[i]; + if (node) { + // update node + node.setProperties(data, this.constants); + } + else { + // create node + node = new Node(properties, this.images, this.groups, this.constants); + nodes[id] = node; + } + } + this.moving = true; + if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { + this._resetLevels(); + this._setupHierarchicalLayout(); + } + this._updateNodeIndexList(); + this._updateValueRange(nodes); + this._markAllEdgesAsDirty(); + }; - // 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 - }; - this.detect(eventData); - }, + Network.prototype._markAllEdgesAsDirty = function() { + for (var edgeId in this.edges) { + this.edges[edgeId].colorDirty = true; + } + } - /** - * Hammer.gesture detection - * @method detect - * @param {Object} eventData - * @return {any} - */ - detect: function detect(eventData) { - if(!this.current || this.stopped) { - return; - } + /** + * 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; - // extend event data with calculations about scale, distance etc - eventData = this.extendEventData(eventData); + // remove from selection + for (var i = 0, len = ids.length; i < len; i++) { + if (this.selectionObj.nodes[ids[i]] !== undefined) { + this.nodes[ids[i]].unselect(); + this._removeFromSelection(this.nodes[ids[i]]); + } + } - // hammer instance and instance options - var inst = this.current.inst, - instOptions = inst.options; + for (var i = 0, len = ids.length; i < len; i++) { + var id = ids[i]; + delete nodes[id]; + } - // call Hammer.gesture handlers - Utils.each(this.gestures, function triggerGesture(gesture) { - // only when the instance options have enabled this gesture - if(!this.stopped && inst.enabled && instOptions[gesture.name]) { - gesture.handler.call(gesture, eventData, inst); - } - }, this); - // store as previous event event - if(this.current) { - this.current.lastEvent = eventData; - } - if(eventData.eventType == EVENT_END) { - this.stopDetect(); - } + this._updateNodeIndexList(); + if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { + this._resetLevels(); + this._setupHierarchicalLayout(); + } + this._updateCalculationNodes(); + this._reconnectEdges(); + this._updateSelection(); + this._updateValueRange(nodes); + }; - return eventData; - }, + /** + * 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; - /** - * 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); + if (edges instanceof DataSet || edges instanceof DataView) { + this.edgesData = edges; + } + else if (Array.isArray(edges)) { + this.edgesData = new DataSet(); + this.edgesData.add(edges); + } + else if (!edges) { + this.edgesData = new DataSet(); + } + else { + throw new TypeError('Array or DataSet expected'); + } - // reset the current - this.current = null; - this.stopped = true; - }, + if (oldEdgesData) { + // unsubscribe from old dataset + util.forEach(this.edgesListeners, function (callback, event) { + oldEdgesData.off(event, callback); + }); + } - /** - * 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; + // remove drawn edges + this.edges = {}; - 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; - } + if (this.edgesData) { + // subscribe to new dataset + var me = this; + util.forEach(this.edgesListeners, function (callback, event) { + me.edgesData.on(event, callback); + }); - if(ev.eventType == EVENT_TOUCH || ev.eventType == EVENT_RELEASE) { - cur.futureCalcEvent = ev; - } + // draw all new nodes + var ids = this.edgesData.getIds(); + this._addEdges(ids); + } - 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._reconnectEdges(); + }; - cur.lastCalcEvent = cur.futureCalcEvent || ev; - cur.futureCalcEvent = ev; - } + /** + * Add edges + * @param {Number[] | String[]} ids + * @private + */ + Network.prototype._addEdges = function (ids) { + var edges = this.edges, + edgesData = this.edgesData; - ev.velocityX = calcData.velocity.x; - ev.velocityY = calcData.velocity.y; - ev.interimAngle = calcData.angle; - ev.interimDirection = calcData.direction; - }, + for (var i = 0, len = ids.length; i < len; i++) { + var id = ids[i]; - /** - * 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; + var oldEdge = edges[id]; + if (oldEdge) { + oldEdge.disconnect(); + } - // 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 data = edgesData.get(id, {"showInternalIds" : true}); + edges[id] = new Edge(data, this, this.constants); + } + this.moving = true; + this._updateValueRange(edges); + this._createBezierNodes(); + this._updateCalculationNodes(); + if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { + this._resetLevels(); + this._setupHierarchicalLayout(); + } + }; - var deltaTime = ev.timeStamp - startEv.timeStamp, - deltaX = ev.center.clientX - startEv.center.clientX, - deltaY = ev.center.clientY - startEv.center.clientY; + /** + * 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]; - this.getCalculatedData(ev, lastEv.center, deltaTime, deltaX, deltaY); + 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; + } + } - Utils.extend(ev, { - startEvent: startEv, + this._createBezierNodes(); + if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { + this._resetLevels(); + this._setupHierarchicalLayout(); + } + this.moving = true; + this._updateValueRange(edges); + }; - deltaTime: deltaTime, - deltaX: deltaX, - deltaY: deltaY, + /** + * Remove existing edges. Non existing ids will be ignored + * @param {Number[] | String[]} ids + * @private + */ + Network.prototype._removeEdges = function (ids) { + var edges = this.edges; - 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) - }); + // remove from selection + for (var i = 0, len = ids.length; i < len; i++) { + if (this.selectionObj.edges[ids[i]] !== undefined) { + edges[ids[i]].unselect(); + this._removeFromSelection(edges[ids[i]]); + } + } - return ev; - }, + 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]; + } + } - /** - * register new gesture - * @method register - * @param {Object} gesture object, see `gestures/` for documentation - * @return {Array} gestures - */ - register: function register(gesture) { - // add an enable gesture options if there is no given - var options = gesture.defaults || {}; - if(options[gesture.name] === undefined) { - options[gesture.name] = true; - } + this.moving = true; + this._updateValueRange(edges); + if (this.constants.hierarchicalLayout.enabled == true && this.initializing == false) { + this._resetLevels(); + this._setupHierarchicalLayout(); + } + this._updateCalculationNodes(); + }; - // extend Hammer default options with the Hammer.gesture options - Utils.extend(Hammer.defaults, options, true); + /** + * 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 = []; + } + } - // set its index - gesture.index = gesture.index || 1000; + for (id in edges) { + if (edges.hasOwnProperty(id)) { + var edge = edges[id]; + edge.from = null; + edge.to = null; + edge.connect(); + } + } + }; - // add Hammer.gesture to the list - this.gestures.push(gesture); + /** + * 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; - // 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; - }); + // determine the range of the objects + var valueMin = undefined; + var valueMax = undefined; + var valueTotal = 0; + for (id in obj) { + if (obj.hasOwnProperty(id)) { + var value = obj[id].getValue(); + if (value !== undefined) { + valueMin = (valueMin === undefined) ? value : Math.min(value, valueMin); + valueMax = (valueMax === undefined) ? value : Math.max(value, valueMax); + valueTotal += value; + } + } + } - return this.gestures; + // adjust the range of all objects + if (valueMin !== undefined && valueMax !== undefined) { + for (id in obj) { + if (obj.hasOwnProperty(id)) { + obj[id].setValueRange(valueMin, valueMax, valueTotal); + } } + } }; - /** - * @module hammer + * Redraw the network with the current data + * chart will be resized too. */ + Network.prototype.redraw = function() { + this.setSize(this.constants.width, this.constants.height); + this._redraw(); + }; /** - * 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} + * Redraw the network with the current data + * @param hidden | used to get the first estimate of the node sizes. only the nodes are drawn after which they are quickly drawn over. + * @private */ - Hammer.Instance = function(element, options) { - var self = this; - - // setup HammerJS window events and register all gestures - // this also sets up the default options - setup(); + Network.prototype._requestRedraw = function(hidden) { + if (this.redrawRequested !== true) { + this.redrawRequested = true; + if (this.requiresTimeout === true) { + window.setTimeout(this._redraw.bind(this, hidden),0); + } + else { + window.requestAnimationFrame(this._redraw.bind(this, hidden, true)); + } + } + }; - /** - * @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 || {}); - - // 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); - } - }); - - /** - * keep a list of user event handlers which needs to be removed when calling 'dispose' - * @property eventHandlers - * @type {Array} - */ - this.eventHandlers = []; - }; - - 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; - }, + Network.prototype._redraw = function(hidden, requested) { + if (hidden === undefined) { + hidden = false; + } + this.redrawRequested = false; + var ctx = this.frame.canvas.getContext('2d'); - /** - * unbind events to the instance - * @method off - * @chainable - * @param {String} gestures - * @param {Function} handler - */ - off: function offEvent(gestures, handler) { - var self = this; + ctx.setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0); - 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; - }, + // clear the canvas + var w = this.frame.canvas.clientWidth; + var h = this.frame.canvas.clientHeight; + ctx.clearRect(0, 0, w, h); - /** - * trigger gesture event - * @method trigger - * @chainable - * @param {String} gesture - * @param {Object} [eventData] - */ - trigger: function triggerEvent(gesture, eventData) { - // optional - if(!eventData) { - eventData = {}; - } + // set scaling and translation + ctx.save(); + ctx.translate(this.translation.x, this.translation.y); + ctx.scale(this.scale, this.scale); - // create DOM event - var event = Hammer.DOCUMENT.createEvent('Event'); - event.initEvent(gesture, true, true); - event.gesture = eventData; + 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) + }; - // trigger on the target if it is in the instance element, - // this is for event delegation tricks - var element = this.element; - if(Utils.hasParent(eventData.target, element)) { - element = eventData.target; - } + if (hidden === false) { + this._doInAllSectors("_drawAllSectorNodes", ctx); + if (this.drag.dragging == false || this.drag.dragging === undefined || this.constants.hideEdgesOnDrag == false) { + this._doInAllSectors("_drawEdges", ctx); + } + } - element.dispatchEvent(event); - return this; - }, + if (this.drag.dragging == false || this.drag.dragging === undefined || this.constants.hideNodesOnDrag == false) { + this._doInAllSectors("_drawNodes",ctx,false); + } - /** - * enable of disable hammer.js detection - * @method enable - * @chainable - * @param {Boolean} state - */ - enable: function enable(state) { - this.enabled = state; - return this; - }, + if (hidden === false) { + if (this.controlNodesActive == true) { + this._doInAllSectors("_drawControlNodes", ctx); + } + } - /** - * dispose this hammer instance - * @method dispose - * @return {Null} - */ - dispose: function dispose() { - var i, eh; + //this._doInSupportSector("_drawNodes",ctx,true); + // this._drawTree(ctx,"#F00F0F"); - // undo all changes made by stop_browser_behavior - Utils.toggleBehavior(this.element, this.options.behavior, false); + // restore original scaling and translation + ctx.restore(); - // unbind all custom event handlers - for(i = -1; (eh = this.eventHandlers[++i]);) { - Utils.off(this.element, eh.gesture, eh.handler); - } + if (hidden === true) { + ctx.clearRect(0, 0, w, h); + } + } - this.eventHandlers = []; + /** + * 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 + }; + } - // unbind the start event listener - Event.off(this.element, EVENT_TYPES[EVENT_START], this.eventStartHandler); + if (offsetX !== undefined) { + this.translation.x = offsetX; + } + if (offsetY !== undefined) { + this.translation.y = offsetY; + } - return null; - } + this.emit('viewChanged'); }; - /** - * @module gestures + * 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 + }; + }; + /** - * 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 + * Scale the network + * @param {Number} scale Scaling factor 1.0 is unscaled + * @private */ + Network.prototype._setScale = function(scale) { + this.scale = scale; + }; + /** - * @event drag - * @param {Object} ev + * Get the current scale of the network + * @return {Number} scale Scaling factor 1.0 is unscaled + * @private */ + Network.prototype._getScale = function() { + return this.scale; + }; + /** - * @event dragstart - * @param {Object} ev + * Convert the X coordinate in DOM-space (coordinate point in browser relative to the container div) to + * the X coordinate in canvas-space (the simulation sandbox, which the camera looks upon) + * @param {number} x + * @returns {number} + * @private */ + Network.prototype._XconvertDOMtoCanvas = function(x) { + return (x - this.translation.x) / this.scale; + }; + /** - * @event dragend - * @param {Object} ev + * 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; + }; + /** - * @event drapleft - * @param {Object} ev + * Convert the Y coordinate in DOM-space (coordinate point in browser relative to the container div) to + * the Y coordinate in canvas-space (the simulation sandbox, which the camera looks upon) + * @param {number} y + * @returns {number} + * @private */ + Network.prototype._YconvertDOMtoCanvas = function(y) { + return (y - this.translation.y) / this.scale; + }; + /** - * @event dragright - * @param {Object} ev + * Convert the Y coordinate in canvas-space (the simulation sandbox, which the camera looks upon) to + * the Y coordinate in DOM-space (coordinate point in browser relative to the container div) + * @param {number} y + * @returns {number} + * @private */ + Network.prototype._YconvertCanvasToDOM = function(y) { + return y * this.scale + this.translation.y ; + }; + + /** - * @event dragup - * @param {Object} ev + * + * @param {object} pos = {x: number, y: number} + * @returns {{x: number, y: number}} + * @constructor */ + Network.prototype.canvasToDOM = function (pos) { + return {x: this._XconvertCanvasToDOM(pos.x), y: this._YconvertCanvasToDOM(pos.y)}; + }; + /** - * @event dragdown - * @param {Object} ev + * + * @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)}; + }; /** - * @param {String} name + * Redraw all nodes + * The 2d context of a HTML canvas can be retrieved by canvas.getContext('2d'); + * @param {CanvasRenderingContext2D} ctx + * @param {Boolean} [alwaysShow] + * @private */ - (function(name) { - var triggered = false; + Network.prototype._drawNodes = function(ctx,alwaysShow) { + if (alwaysShow === undefined) { + alwaysShow = false; + } - function dragGesture(ev, inst) { - var cur = Detection.current; + // first draw the unselected nodes + var nodes = this.nodes; + var selected = []; - // max touches - if(inst.options.dragMaxTouches > 0 && - ev.touches.length > inst.options.dragMaxTouches) { - return; + 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); } + } + } + } - switch(ev.eventType) { - case EVENT_START: - triggered = false; - break; - - 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; - } - - var startCenter = cur.startEvent.center; + // 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); + } + } + }; - // we are dragging! - if(cur.name != name) { - cur.name = name; - if(inst.options.dragDistanceCorrection && ev.distance > 0) { - // When a drag is triggered, set the event center to dragMinDistance pixels from the original event center. - // Without this correction, the dragged distance would jumpstart at dragMinDistance pixels instead of at 0. - // It might be useful to save the original start point somewhere - var factor = Math.abs(inst.options.dragMinDistance / ev.distance); - startCenter.pageX += ev.deltaX * factor; - startCenter.pageY += ev.deltaY * factor; - startCenter.clientX += ev.deltaX * factor; - startCenter.clientY += ev.deltaY * factor; + /** + * Redraw all edges + * The 2d context of a HTML canvas can be retrieved by canvas.getContext('2d'); + * @param {CanvasRenderingContext2D} ctx + * @private + */ + Network.prototype._drawEdges = function(ctx) { + var edges = this.edges; + for (var id in edges) { + if (edges.hasOwnProperty(id)) { + var edge = edges[id]; + edge.setScale(this.scale); + if (edge.connected === true) { + edges[id].draw(ctx); + } + } + } + }; - // recalculate event data using new start point - ev = Detection.extendEventData(ev); - } - } + /** + * 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); + } + } + }; - // lock drag to axis? - if(cur.lastEvent.dragLockToAxis || - ( inst.options.dragLockToAxis && - inst.options.dragLockMinDistance <= ev.distance - )) { - ev.dragLockToAxis = true; - } + /** + * Find a stable position for all nodes + * @private + */ + Network.prototype._stabilize = function() { + if (this.constants.freezeForStabilization == true) { + this._freezeDefinedNodes(); + } - // 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; - } - } + // find stable position + var count = 0; + while (this.moving && count < this.constants.stabilizationIterations) { + this._physicsTick(); + count++; + } - // 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); + if (this.constants.zoomExtentOnStabilize == true) { + this.zoomExtent({duration:0}, false, true); + } - var isVertical = Utils.isVertical(ev.direction); + if (this.constants.freezeForStabilization == true) { + this._restoreFrozenNodes(); + } - // block the browser events - if((inst.options.dragBlockVertical && isVertical) || - (inst.options.dragBlockHorizontal && !isVertical)) { - ev.preventDefault(); - } - break; + this.emit("stabilizationIterationsDone"); + }; - case EVENT_RELEASE: - if(triggered && ev.changedLength <= inst.options.dragMaxTouches) { - inst.trigger(name + 'end', ev); - triggered = false; - } - break; + /** + * When initializing and stabilizing, we can freeze nodes with a predefined position. This greatly speeds up stabilization + * because only the supportnodes for the smoothCurves have to settle. + * + * @private + */ + Network.prototype._freezeDefinedNodes = function() { + var nodes = this.nodes; + for (var id in nodes) { + if (nodes.hasOwnProperty(id)) { + if (nodes[id].x != null && nodes[id].y != null) { + nodes[id].fixedData.x = nodes[id].xFixed; + nodes[id].fixedData.y = nodes[id].yFixed; + nodes[id].xFixed = true; + nodes[id].yFixed = true; + } + } + } + }; - case EVENT_END: - triggered = false; - break; - } + /** + * Unfreezes the nodes that have been frozen by _freezeDefinedNodes. + * + * @private + */ + Network.prototype._restoreFrozenNodes = function() { + var nodes = this.nodes; + for (var id in nodes) { + if (nodes.hasOwnProperty(id)) { + if (nodes[id].fixedData.x != null) { + nodes[id].xFixed = nodes[id].fixedData.x; + nodes[id].yFixed = nodes[id].fixedData.y; + } } + } + }; - 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, + /** + * 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[id] !== undefined) { + if (nodes[id].isMoving(vmin) == true) { + return true; + } + } + } + return false; + }; - /** - * 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, + /** + * /** + * 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; - /** - * same as `dragBlockHorizontal`, but for vertical movement - * @property dragBlockVertical - * @type {Boolean} - * @default false - */ - dragBlockVertical: false, + 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; + } + } + } - /** - * 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, + if (nodesPresent == true) { + var vminCorrected = this.constants.minVelocity / Math.max(this.scale,0.05); + if (vminCorrected > 0.5*this.constants.maxVelocity) { + return true; + } + else { + return this._isMoving(vminCorrected); + } + } + return 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'); + + Network.prototype._revertPhysicsState = function() { + var nodes = this.nodes; + for (var nodeId in nodes) { + if (nodes.hasOwnProperty(nodeId)) { + nodes[nodeId].revertPosition(); + } + } + } + + Network.prototype._revertPhysicsTick = function() { + this._doInAllActiveSectors("_revertPhysicsState"); + if (this.constants.smoothCurves.enabled == true && this.constants.smoothCurves.dynamic == true) { + this._doInSupportSector("_revertPhysicsState"); + } + } /** - * @module gestures - */ - /** - * trigger a simple gesture event, so you can do anything in your handler. - * only usable if you know what your doing... + * A single simulation step (or "tick") in the physics simulation * - * @class Gesture - * @static - */ - /** - * @event gesture - * @param {Object} ev + * @private */ - Hammer.gestures.Gesture = { - name: 'gesture', - index: 1337, - handler: function releaseGesture(ev, inst) { - inst.trigger(this.name, ev); + Network.prototype._physicsTick = function() { + if (!this.freezeSimulationEnabled) { + if (this.moving == true) { + var mainMovingStatus = false; + var supportMovingStatus = false; + + this._doInAllActiveSectors("_initializeForceCalculation"); + var mainMoving = this._doInAllActiveSectors("_discreteStepNodes"); + if (this.constants.smoothCurves.enabled == true && this.constants.smoothCurves.dynamic == true) { + supportMovingStatus = this._doInSupportSector("_discreteStepNodes"); + } + + // gather movement data from all sectors, if one moves, we are NOT stabilzied + for (var i = 0; i < mainMoving.length; i++) { + mainMovingStatus = mainMoving[i] || mainMovingStatus; + } + + // determine if the network has stabilzied + this.moving = mainMovingStatus || supportMovingStatus; + if (this.moving == false) { + this._revertPhysicsTick(); + } + else { + // this is here to ensure that there is no start event when the network is already stable. + if (this.startedStabilization == false) { + this.emit("startStabilization"); + this.startedStabilization = true; + } + } + + this.stabilizationIterations++; } + } }; - /** - * @module gestures - */ - /** - * Touch stays at the same place for x time - * - * @class Hold - * @static - */ - /** - * @event hold - * @param {Object} ev - */ /** - * @param {String} name + * 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 */ - (function(name) { - var timer; + Network.prototype._animationStep = function() { + // reset the timer so a new scheduled animation step can be set + this.timer = undefined; - function holdGesture(ev, inst) { - var options = inst.options, - current = Detection.current; + if (this.requiresTimeout == true) { + // this schedules a new animation step + this.start(); + } - switch(ev.eventType) { - case EVENT_START: - clearTimeout(timer); + // handle the keyboad movement + this._handleNavigation(); - // set the gesture so we can check in the timeout if it still is - current.name = name; + // check if the physics have settled + if (this.moving == true) { + var startTime = Date.now(); - // 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; + this._physicsTick(); + var physicsTime = Date.now() - startTime; - case EVENT_MOVE: - if(ev.distance > options.holdThreshold) { - clearTimeout(timer); - } - break; + // run double speed if it is a little graph + if ((this.renderTimestep - this.renderTime > 2 * physicsTime || this.runDoubleSpeed == true) && this.moving == true) { + this._physicsTick(); - case EVENT_RELEASE: - clearTimeout(timer); - break; - } + // this makes sure there is no jitter. The decision is taken once to run it at double speed. + if (this.renderTime != 0) { + this.runDoubleSpeed = true + } } + } - Hammer.gestures.Hold = { - name: name, - index: 10, - defaults: { - /** - * @property holdTimeout - * @type {Number} - * @default 500 - */ - holdTimeout: 500, + var renderStartTime = Date.now(); + this._redraw(); + this.renderTime = Date.now() - renderStartTime; - /** - * movement allowed while holding - * @property holdThreshold - * @type {Number} - * @default 2 - */ - holdThreshold: 2 - }, - handler: holdGesture - }; - })('hold'); + if (this.requiresTimeout == false) { + // this schedules a new animation step + this.start(); + } + }; + + if (typeof window !== 'undefined') { + window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || + window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; + } /** - * @module gestures - */ - /** - * when a touch is being released from the page - * - * @class Release - * @static - */ - /** - * @event release - * @param {Object} ev + * Schedule a animation step with the refreshrate interval. */ - Hammer.gestures.Release = { - name: 'release', - index: Infinity, - handler: function releaseGesture(ev, inst) { - if(ev.eventType == EVENT_RELEASE) { - inst.trigger(this.name, ev); - } + Network.prototype.start = function() { + if (this.freezeSimulationEnabled == true) { + this.moving = false; + } + if (this.moving == true || this.xIncrement != 0 || this.yIncrement != 0 || this.zoomIncrement != 0 || this.animating == true) { + if (!this.timer) { + if (this.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)); // wait this.renderTimeStep milliseconds and perform the animation step function + } + } + } + else { + this._requestRedraw(); + // this check is to ensure that the network does not emit these events if it was already stabilized and setOptions is called (setting moving to true and calling start()) + if (this.stabilizationIterations > 1) { + // trigger the "stabilized" event. + // The event is triggered on the next tick, to prevent the case that + // it is fired while initializing the Network, in which case you would not + // be able to catch it + var me = this; + var params = { + iterations: me.stabilizationIterations + }; + this.stabilizationIterations = 0; + this.startedStabilization = false; + setTimeout(function () { + me.emit("stabilized", params); + }, 0); + } + else { + this.stabilizationIterations = 0; } + } }; + /** - * @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(); - * }); - * ```` + * Move the network according to the keyboard presses. * - * @class Swipe - * @static - */ - /** - * @event swipe - * @param {Object} ev - */ - /** - * @event swipeleft - * @param {Object} ev - */ - /** - * @event swiperight - * @param {Object} ev - */ - /** - * @event swipeup - * @param {Object} ev + * @private */ + Network.prototype._handleNavigation = function() { + if (this.xIncrement != 0 || this.yIncrement != 0) { + var translation = this._getTranslation(); + this._setTranslation(translation.x+this.xIncrement, translation.y+this.yIncrement); + } + if (this.zoomIncrement != 0) { + var center = { + x: this.frame.canvas.clientWidth / 2, + y: this.frame.canvas.clientHeight / 2 + }; + this._zoom(this.scale*(1 + this.zoomIncrement), center); + } + }; + + /** - * @event swipedown - * @param {Object} ev + * Freeze the _animationStep */ - Hammer.gestures.Swipe = { - name: 'swipe', - index: 40, - defaults: { - /** - * @property swipeMinTouches - * @type {Number} - * @default 1 - */ - swipeMinTouches: 1, + Network.prototype.freezeSimulation = function(freeze) { + if (freeze == true) { + this.freezeSimulationEnabled = true; + this.moving = false; + } + else { + this.freezeSimulationEnabled = false; + this.moving = true; + this.start(); + } + }; - /** - * @property swipeMaxTouches - * @type {Number} - * @default 1 - */ - swipeMaxTouches: 1, - /** - * horizontal swipe velocity - * @property swipeVelocityX - * @type {Number} - * @default 0.6 - */ - swipeVelocityX: 0.6, + /** + * This function cleans the support nodes if they are not needed and adds them when they are. + * + * @param {boolean} [disableStart] + * @private + */ + Network.prototype._configureSmoothCurves = function(disableStart) { + if (disableStart === undefined) { + disableStart = true; + } + if (this.constants.smoothCurves.enabled == true && this.constants.smoothCurves.dynamic == true) { + this._createBezierNodes(); + // cleanup unused support nodes + for (var nodeId in this.sectors['support']['nodes']) { + if (this.sectors['support']['nodes'].hasOwnProperty(nodeId)) { + if (this.edges[this.sectors['support']['nodes'][nodeId].parentEdgeId] === undefined) { + delete this.sectors['support']['nodes'][nodeId]; + } + } + } + } + else { + // delete the support nodes + this.sectors['support']['nodes'] = {}; + for (var edgeId in this.edges) { + if (this.edges.hasOwnProperty(edgeId)) { + this.edges[edgeId].via = null; + } + } + } - /** - * vertical swipe velocity - * @property swipeVelocityY - * @type {Number} - * @default 0.6 - */ - swipeVelocityY: 0.6 - }, - handler: function swipeGesture(ev, inst) { - if(ev.eventType == EVENT_RELEASE) { - var touches = ev.touches.length, - options = inst.options; + this._updateCalculationNodes(); + if (!disableStart) { + this.moving = true; + this.start(); + } + }; - // max touches - if(touches < options.swipeMinTouches || - touches > options.swipeMaxTouches) { - return; - } - // when the distance we moved is too small we skip this gesture - // or we can be already in dragging - if(ev.velocityX > options.swipeVelocityX || - ev.velocityY > options.swipeVelocityY) { - // trigger swipe events - inst.trigger(this.name, ev); - inst.trigger(this.name + ev.direction, ev); - } + /** + * 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(specificEdges) { + if (specificEdges === undefined) { + specificEdges = this.edges; + } + if (this.constants.smoothCurves.enabled == true && this.constants.smoothCurves.dynamic == true) { + for (var edgeId in specificEdges) { + if (specificEdges.hasOwnProperty(edgeId)) { + var edge = specificEdges[edgeId]; + if (edge.via == null) { + var nodeId = "edgeId:".concat(edge.id); + this.sectors['support']['nodes'][nodeId] = new Node( + {id:nodeId, + mass:1, + shape:'circle', + image:"", + internalMultiplier:1 + },{},{},this.constants); + edge.via = this.sectors['support']['nodes'][nodeId]; + edge.via.parentEdgeId = edge.id; + edge.positionBezierNode(); } + } } + } }; /** - * @module gestures - */ - /** - * Single tap and a double tap on a place + * load the functions that load the mixins into the prototype. * - * @class Tap - * @static + * @private */ + Network.prototype._initializeMixinLoaders = function () { + for (var mixin in MixinLoader) { + if (MixinLoader.hasOwnProperty(mixin)) { + Network.prototype[mixin] = MixinLoader[mixin]; + } + } + }; + /** - * @event tap - * @param {Object} ev - */ - /** - * @event doubletap - * @param {Object} ev + * Load the XY positions of the nodes into the dataset. */ + Network.prototype.storePosition = function() { + console.log("storePosition is depricated: use .storePositions() from now on.") + this.storePositions(); + }; /** - * @param {String} name + * Load the XY positions of the nodes into the dataset. */ - (function(name) { - var hasMoved = false; - - function tapGesture(ev, inst) { - var options = inst.options, - current = Detection.current, - prev = Detection.previous, - sincePrev, - didDoubleTap; - - switch(ev.eventType) { - case EVENT_START: - hasMoved = false; - break; - - case EVENT_MOVE: - hasMoved = hasMoved || (ev.distance > options.tapMaxDistance); - break; - - case EVENT_END: - if(!Utils.inStr(ev.srcEvent.type, 'cancel') && ev.deltaTime < options.tapMaxTime && !hasMoved) { - // previous gesture, for the double tap since these are two different gesture detections - sincePrev = prev && prev.lastEvent && ev.timeStamp - prev.lastEvent.timeStamp; - didDoubleTap = false; - - // check if double tap - if(prev && prev.name == name && - (sincePrev && sincePrev < options.doubleTapInterval) && - ev.distance < options.doubleTapDistance) { - inst.trigger('doubletap', ev); - didDoubleTap = true; - } - - // do a single tap - if(!didDoubleTap || options.tapAlways) { - current.name = name; - inst.trigger(current.name, ev); - } - } - break; - } + Network.prototype.storePositions = 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); + }; - 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'); - - /** - * @module gestures - */ /** - * when a touch is being touched at the page - * - * @class Touch - * @static - */ - /** - * @event touch - * @param {Object} ev + * Return the positions of the nodes. */ - Hammer.gestures.Touch = { - name: 'touch', - index: -Infinity, - defaults: { - /** - * call preventDefault at touchstart, and makes the element blocking by disabling the scrolling of the page, - * but it improves gestures like transforming and dragging. - * be careful with using this, it can be very annoying for users to be stuck on the page - * @property preventDefault - * @type {Boolean} - * @default false - */ - preventDefault: false, - - /** - * disable mouse events, so only touch (or pen!) input triggers events - * @property preventMouse - * @type {Boolean} - * @default false - */ - preventMouse: false - }, - handler: function touchGesture(ev, inst) { - if(inst.options.preventMouse && ev.pointerType == POINTER_MOUSE) { - ev.stopDetect(); - return; - } - - if(inst.options.preventDefault) { - ev.preventDefault(); - } - - if(ev.eventType == EVENT_TOUCH) { - inst.trigger('touch', ev); + Network.prototype.getPositions = function(ids) { + var dataArray = {}; + if (ids !== undefined) { + if (Array.isArray(ids) == true) { + for (var i = 0; i < ids.length; i++) { + if (this.nodes[ids[i]] !== undefined) { + var node = this.nodes[ids[i]]; + dataArray[ids[i]] = {x: Math.round(node.x), y: Math.round(node.y)}; } + } } + else { + if (this.nodes[ids] !== undefined) { + var node = this.nodes[ids]; + dataArray[ids] = {x: Math.round(node.x), y: Math.round(node.y)}; + } + } + } + else { + for (var nodeId in this.nodes) { + if (this.nodes.hasOwnProperty(nodeId)) { + var node = this.nodes[nodeId]; + dataArray[nodeId] = {x: Math.round(node.x), y: Math.round(node.y)}; + } + } + } + return dataArray; }; - /** - * @module gestures - */ - /** - * User want to scale or rotate with 2 fingers - * Preventing the default browser behavior is a good way to improve feel and working. This can be done with the - * `preventDefault` option. - * - * @class Transform - * @static - */ - /** - * @event transform - * @param {Object} ev - */ - /** - * @event transformstart - * @param {Object} ev - */ - /** - * @event transformend - * @param {Object} ev - */ - /** - * @event pinchin - * @param {Object} ev - */ - /** - * @event pinchout - * @param {Object} ev - */ - /** - * @event rotate - * @param {Object} ev - */ + /** - * @param {String} name + * Center a node in view. + * + * @param {Number} nodeId + * @param {Number} [options] */ - (function(name) { - var triggered = false; - - function transformGesture(ev, inst) { - switch(ev.eventType) { - case EVENT_START: - triggered = false; - break; - - case EVENT_MOVE: - // at least multitouch - if(ev.touches.length < 2) { - return; - } - - var scaleThreshold = Math.abs(1 - ev.scale); - var rotationThreshold = Math.abs(ev.rotation); - - // 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; - - // 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); - } - - // trigger pinch event - if(scaleThreshold > inst.options.transformMinScale) { - inst.trigger('pinch', ev); - inst.trigger('pinch' + (ev.scale < 1 ? 'in' : 'out'), ev); - } - break; - - case EVENT_RELEASE: - if(triggered && ev.changedLength < 2) { - inst.trigger(name + 'end', ev); - triggered = false; - } - break; - } + Network.prototype.focusOnNode = function (nodeId, options) { + if (this.nodes.hasOwnProperty(nodeId)) { + if (options === undefined) { + options = {}; } + var nodePosition = {x: this.nodes[nodeId].x, y: this.nodes[nodeId].y}; + options.position = nodePosition; + options.lockedOnNode = nodeId; - 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.moveTo(options) + } + else { + console.log("This nodeId cannot be found."); + } + }; /** - * @module hammer + * + * @param {Object} options | options.offset = {x:Number, y:Number} // offset from the center in DOM pixels + * | options.scale = Number // scale to move to + * | options.position = {x:Number, y:Number} // position to move to + * | options.animation = {duration:Number, easingFunction:String} || Boolean // position to move to */ + Network.prototype.moveTo = function (options) { + if (options === undefined) { + options = {}; + return; + } + if (options.offset === undefined) {options.offset = {x: 0, y: 0}; } + if (options.offset.x === undefined) {options.offset.x = 0; } + if (options.offset.y === undefined) {options.offset.y = 0; } + if (options.scale === undefined) {options.scale = this._getScale(); } + if (options.position === undefined) {options.position = this._getTranslation();} + if (options.animation === undefined) {options.animation = {duration:0}; } + if (options.animation === false ) {options.animation = {duration:0}; } + if (options.animation === true ) {options.animation = {}; } + if (options.animation.duration === undefined) {options.animation.duration = 1000; } // default duration + if (options.animation.easingFunction === undefined) {options.animation.easingFunction = "easeInOutQuad"; } // default easing function - // AMD export - if(true) { - !(__WEBPACK_AMD_DEFINE_RESULT__ = function() { - return Hammer; - }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); - // commonjs export - } else if(typeof module !== 'undefined' && module.exports) { - module.exports = Hammer; - // browser export - } else { - window.Hammer = Hammer; - } - - })(window); - -/***/ }, -/* 58 */ -/***/ function(module, exports, __webpack_require__) { + this.animateView(options); + }; - var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;"use strict"; /** - * Created by Alex on 11/6/2014. + * + * @param {Object} options | options.offset = {x:Number, y:Number} // offset from the center in DOM pixels + * | options.time = Number // animation time in milliseconds + * | options.scale = Number // scale to animate to + * | options.position = {x:Number, y:Number} // position to animate to + * | options.easingFunction = String // linear, easeInQuad, easeOutQuad, easeInOutQuad, + * // easeInCubic, easeOutCubic, easeInOutCubic, + * // easeInQuart, easeOutQuart, easeInOutQuart, + * // easeInQuint, easeOutQuint, easeInOutQuint */ + Network.prototype.animateView = function (options) { + if (options === undefined) { + options = {}; + return; + } - // https://github.com/umdjs/umd/blob/master/returnExports.js#L40-L60 - // if the module has no dependencies, the above pattern can be simplified to - (function (root, factory) { - if (true) { - // AMD. Register as an anonymous module. - !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); - } else if (typeof exports === 'object') { - // Node. Does not work with strict CommonJS, but - // only CommonJS-like environments that support module.exports, - // like Node. - module.exports = factory(); - } else { - // Browser globals (root is window) - root.keycharm = factory(); - } - }(this, function () { - - function keycharm(options) { - var preventDefault = options && options.preventDefault || false; - - var container = options && options.container || window; - var _exportFunctions = {}; - var _bound = {keydown:{}, keyup:{}}; - var _keys = {}; - var i; - - // a - z - for (i = 97; i <= 122; i++) {_keys[String.fromCharCode(i)] = {code:65 + (i - 97), shift: false};} - // A - Z - for (i = 65; i <= 90; i++) {_keys[String.fromCharCode(i)] = {code:i, shift: true};} - // 0 - 9 - for (i = 0; i <= 9; i++) {_keys['' + i] = {code:48 + i, shift: false};} - // F1 - F12 - for (i = 1; i <= 12; i++) {_keys['F' + i] = {code:111 + i, shift: false};} - // num0 - num9 - for (i = 0; i <= 9; i++) {_keys['num' + i] = {code:96 + i, shift: false};} - - // numpad misc - _keys['num*'] = {code:106, shift: false}; - _keys['num+'] = {code:107, shift: false}; - _keys['num-'] = {code:109, shift: false}; - _keys['num/'] = {code:111, shift: false}; - _keys['num.'] = {code:110, shift: false}; - // arrows - _keys['left'] = {code:37, shift: false}; - _keys['up'] = {code:38, shift: false}; - _keys['right'] = {code:39, shift: false}; - _keys['down'] = {code:40, shift: false}; - // extra keys - _keys['space'] = {code:32, shift: false}; - _keys['enter'] = {code:13, shift: false}; - _keys['shift'] = {code:16, shift: undefined}; - _keys['esc'] = {code:27, shift: false}; - _keys['backspace'] = {code:8, shift: false}; - _keys['tab'] = {code:9, shift: false}; - _keys['ctrl'] = {code:17, shift: false}; - _keys['alt'] = {code:18, shift: false}; - _keys['delete'] = {code:46, shift: false}; - _keys['pageup'] = {code:33, shift: false}; - _keys['pagedown'] = {code:34, shift: false}; - // symbols - _keys['='] = {code:187, shift: false}; - _keys['-'] = {code:189, shift: false}; - _keys[']'] = {code:221, shift: false}; - _keys['['] = {code:219, shift: false}; - - - - var down = function(event) {handleEvent(event,'keydown');}; - var up = function(event) {handleEvent(event,'keyup');}; - - // handle the actualy bound key with the event - var handleEvent = function(event,type) { - if (_bound[type][event.keyCode] !== undefined) { - var bound = _bound[type][event.keyCode]; - for (var i = 0; i < bound.length; i++) { - if (bound[i].shift === undefined) { - bound[i].fn(event); - } - else if (bound[i].shift == true && event.shiftKey == true) { - bound[i].fn(event); - } - else if (bound[i].shift == false && event.shiftKey == false) { - bound[i].fn(event); - } - } - - if (preventDefault == true) { - event.preventDefault(); - } - } - }; - - // bind a key to a callback - _exportFunctions.bind = function(key, callback, type) { - if (type === undefined) { - type = 'keydown'; - } - if (_keys[key] === undefined) { - throw new Error("unsupported key: " + key); - } - if (_bound[type][_keys[key].code] === undefined) { - _bound[type][_keys[key].code] = []; - } - _bound[type][_keys[key].code].push({fn:callback, shift:_keys[key].shift}); - }; - - - // bind all keys to a call back (demo purposes) - _exportFunctions.bindAll = function(callback, type) { - if (type === undefined) { - type = 'keydown'; - } - for (var key in _keys) { - if (_keys.hasOwnProperty(key)) { - _exportFunctions.bind(key,callback,type); - } - } - }; - - // get the key label from an event - _exportFunctions.getKey = function(event) { - for (var key in _keys) { - if (_keys.hasOwnProperty(key)) { - if (event.shiftKey == true && _keys[key].shift == true && event.keyCode == _keys[key].code) { - return key; - } - else if (event.shiftKey == false && _keys[key].shift == false && event.keyCode == _keys[key].code) { - return key; - } - else if (event.keyCode == _keys[key].code && key == 'shift') { - return key; - } - } - } - return "unknown key, currently not supported"; - }; - - // unbind either a specific callback from a key or all of them (by leaving callback undefined) - _exportFunctions.unbind = function(key, callback, type) { - if (type === undefined) { - type = 'keydown'; - } - if (_keys[key] === undefined) { - throw new Error("unsupported key: " + key); - } - if (callback !== undefined) { - var newBindings = []; - var bound = _bound[type][_keys[key].code]; - if (bound !== undefined) { - for (var i = 0; i < bound.length; i++) { - if (!(bound[i].fn == callback && bound[i].shift == _keys[key].shift)) { - newBindings.push(_bound[type][_keys[key].code][i]); - } - } - } - _bound[type][_keys[key].code] = newBindings; - } - else { - _bound[type][_keys[key].code] = []; - } - }; - - // reset all bound variables. - _exportFunctions.reset = function() { - _bound = {keydown:{}, keyup:{}}; - }; - - // unbind all listeners and reset all variables. - _exportFunctions.destroy = function() { - _bound = {keydown:{}, keyup:{}}; - container.removeEventListener('keydown', down, true); - container.removeEventListener('keyup', up, true); - }; - - // create listeners. - container.addEventListener('keydown',down,true); - container.addEventListener('keyup',up,true); - - // return the public functions. - return _exportFunctions; - } - - return keycharm; - })); - - - - -/***/ }, -/* 59 */ -/***/ function(module, exports, __webpack_require__) { - - var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(global, module) {//! moment.js - //! version : 2.9.0 - //! authors : Tim Wood, Iskren Chernev, Moment.js contributors - //! license : MIT - //! momentjs.com - - (function (undefined) { - /************************************ - Constants - ************************************/ - - var moment, - VERSION = '2.9.0', - // the global-scope this is NOT the global object in Node.js - globalScope = (typeof global !== 'undefined' && (typeof window === 'undefined' || window === global.window)) ? global : this, - oldGlobalMoment, - round = Math.round, - hasOwnProperty = Object.prototype.hasOwnProperty, - i, - - YEAR = 0, - MONTH = 1, - DATE = 2, - HOUR = 3, - MINUTE = 4, - SECOND = 5, - MILLISECOND = 6, - - // internal storage for locale config files - locales = {}, - - // extra moment internal properties (plugins register props here) - momentProperties = [], - - // check for nodeJS - hasModule = (typeof module !== 'undefined' && module && module.exports), - - // 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)$/, - - // 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|X|zz?|ZZ?|.)/g, - localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, - - // 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) - parseTokenOffsetMs = /[\+\-]?\d+/, // 1234567890123 - parseTokenTimestampMs = /[\+\-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123 - - //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 - - // iso 8601 regex - // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00) - isoRegex = /^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/, - - isoFormat = 'YYYY-MM-DDTHH:mm:ssZ', - - 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}/] - ], - - // 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/] - ], - - // timezone chunker '+10:00' > ['10', '00'] or '-1530' > ['-', '15', '30'] - parseTimezoneChunker = /([\+\-]|\d\d)/gi, - - // 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' - }, - - camelFunctions = { - dayofyear : 'dayOfYear', - isoweekday : 'isoWeekday', - isoweek : 'isoWeek', - weekyear : 'weekYear', - isoweekyear : 'isoWeekYear' - }, - - // format function strings - formatFunctions = {}, - - // default relative time thresholds - relativeTimeThresholds = { - s: 45, // seconds to minute - m: 45, // minutes to hour - h: 22, // hours to day - d: 26, // days to month - M: 11 // months to year - }, - - // tokens to ordinalize and pad - ordinalizeTokens = 'DDD w W M D d'.split(' '), - paddedTokens = 'M D H h m s w W'.split(' '), - - formatTokenFunctions = { - M : function () { - return this.month() + 1; - }, - MMM : function (format) { - return this.localeData().monthsShort(this, format); - }, - MMMM : function (format) { - return this.localeData().months(this, format); - }, - D : function () { - return this.date(); - }, - DDD : function () { - return this.dayOfYear(); - }, - d : function () { - return this.day(); - }, - dd : function (format) { - return this.localeData().weekdaysMin(this, format); - }, - ddd : function (format) { - return this.localeData().weekdaysShort(this, format); - }, - dddd : function (format) { - return this.localeData().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.localeData().meridiem(this.hours(), this.minutes(), true); - }, - A : function () { - return this.localeData().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.utcOffset(), - b = '+'; - if (a < 0) { - a = -a; - b = '-'; - } - return b + leftZeroFill(toInt(a / 60), 2) + ':' + leftZeroFill(toInt(a) % 60, 2); - }, - ZZ : function () { - var a = this.utcOffset(), - 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.valueOf(); - }, - X : function () { - return this.unix(); - }, - Q : function () { - return this.quarter(); - } - }, - - deprecations = {}, + // release if something focussed on the node + this.releaseNode(); + if (options.locked == true) { + this.lockedOnNodeId = options.lockedOnNode; + this.lockedOnNodeOffset = options.offset; + } - lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin'], + // forcefully complete the old animation if it was still running + if (this.easingTime != 0) { + this._transitionRedraw(1); // by setting easingtime to 1, we finish the animation. + } - updateInProgress = false; + this.sourceScale = this._getScale(); + this.sourceTranslation = this._getTranslation(); + this.targetScale = options.scale; - // 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'); - } - } + // set the scale so the viewCenter is based on the correct zoom level. This is overridden in the transitionRedraw + // but at least then we'll have the target transition + this._setScale(this.targetScale); + var viewCenter = this.DOMtoCanvas({x: 0.5 * this.frame.canvas.clientWidth, y: 0.5 * this.frame.canvas.clientHeight}); + var distanceFromCenter = { // offset from view, distance view has to change by these x and y to center the node + x: viewCenter.x - options.position.x, + y: viewCenter.y - options.position.y + }; + this.targetTranslation = { + x: this.sourceTranslation.x + distanceFromCenter.x * this.targetScale + options.offset.x, + y: this.sourceTranslation.y + distanceFromCenter.y * this.targetScale + options.offset.y + }; - function hasOwnProp(a, b) { - return hasOwnProperty.call(a, b); + // if the time is set to 0, don't do an animation + if (options.animation.duration == 0) { + if (this.lockedOnNodeId != null) { + this._classicRedraw = this._redraw; + this._redraw = this._lockedRedraw; } - - 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 - }; + else { + this._setScale(this.targetScale); + this._setTranslation(this.targetTranslation.x, this.targetTranslation.y); + this._redraw(); } + } + else { + this.animating = true; + this.animationSpeed = 1 / (this.renderRefreshRate * options.animation.duration * 0.001) || 1 / this.renderRefreshRate; + this.animationEasingFunction = options.animation.easingFunction; + this._classicRedraw = this._redraw; + this._redraw = this._transitionRedraw; + this._redraw(); + this.start(); + } + }; - function printMsg(msg) { - if (moment.suppressDeprecationWarnings === false && - typeof console !== 'undefined' && console.warn) { - console.warn('Deprecation warning: ' + msg); - } - } + /** + * used to animate smoothly by hijacking the redraw function. + * @private + */ + Network.prototype._lockedRedraw = function () { + var nodePosition = {x: this.nodes[this.lockedOnNodeId].x, y: this.nodes[this.lockedOnNodeId].y}; + var viewCenter = this.DOMtoCanvas({x: 0.5 * this.frame.canvas.clientWidth, y: 0.5 * this.frame.canvas.clientHeight}); + var distanceFromCenter = { // offset from view, distance view has to change by these x and y to center the node + x: viewCenter.x - nodePosition.x, + y: viewCenter.y - nodePosition.y + }; + var sourceTranslation = this._getTranslation(); + var targetTranslation = { + x: sourceTranslation.x + distanceFromCenter.x * this.scale + this.lockedOnNodeOffset.x, + y: sourceTranslation.y + distanceFromCenter.y * this.scale + this.lockedOnNodeOffset.y + }; - function deprecate(msg, fn) { - var firstTime = true; - return extend(function () { - if (firstTime) { - printMsg(msg); - firstTime = false; - } - return fn.apply(this, arguments); - }, fn); - } + this._setTranslation(targetTranslation.x,targetTranslation.y); + this._classicRedraw(); + } - function deprecateSimple(name, msg) { - if (!deprecations[name]) { - printMsg(msg); - deprecations[name] = true; - } - } + Network.prototype.releaseNode = function () { + if (this.lockedOnNodeId != null) { + this._redraw = this._classicRedraw; + this.lockedOnNodeId = null; + this.lockedOnNodeOffset = null; + } + } - function padToken(func, count) { - return function (a) { - return leftZeroFill(func.call(this, a), count); - }; - } - function ordinalizeToken(func, period) { - return function (a) { - return this.localeData().ordinal(func.call(this, a), period); - }; - } + /** + * + * @param easingTime + * @private + */ + Network.prototype._transitionRedraw = function (easingTime) { + this.easingTime = easingTime || this.easingTime + this.animationSpeed; + this.easingTime += this.animationSpeed; - function monthDiff(a, b) { - // difference in months - var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()), - // b is in (anchor - 1 month, anchor + 1 month) - anchor = a.clone().add(wholeMonthDiff, 'months'), - anchor2, adjust; + var progress = util.easingFunctions[this.animationEasingFunction](this.easingTime); - if (b - anchor < 0) { - anchor2 = a.clone().add(wholeMonthDiff - 1, 'months'); - // linear across the month - adjust = (b - anchor) / (anchor - anchor2); - } else { - anchor2 = a.clone().add(wholeMonthDiff + 1, 'months'); - // linear across the month - adjust = (b - anchor) / (anchor2 - anchor); - } + this._setScale(this.sourceScale + (this.targetScale - this.sourceScale) * progress); + this._setTranslation( + this.sourceTranslation.x + (this.targetTranslation.x - this.sourceTranslation.x) * progress, + this.sourceTranslation.y + (this.targetTranslation.y - this.sourceTranslation.y) * progress + ); - return -(wholeMonthDiff + adjust); - } + this._classicRedraw(); - while (ordinalizeTokens.length) { - i = ordinalizeTokens.pop(); - formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i], i); + // cleanup + if (this.easingTime >= 1.0) { + this.animating = false; + this.easingTime = 0; + if (this.lockedOnNodeId != null) { + this._redraw = this._lockedRedraw; } - while (paddedTokens.length) { - i = paddedTokens.pop(); - formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2); + else { + this._redraw = this._classicRedraw; } - formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3); + this.emit("animationFinished"); + } + }; + Network.prototype._classicRedraw = function () { + // placeholder function to be overloaded by animations; + }; - function meridiemFixWrap(locale, hour, meridiem) { - var isPm; + /** + * Returns true when the Network is active. + * @returns {boolean} + */ + Network.prototype.isActive = function () { + return !this.activator || this.activator.active; + }; - if (meridiem == null) { - // nothing to do - return hour; + + /** + * Sets the scale + * @returns {Number} + */ + Network.prototype.setScale = function () { + return this._setScale(); + }; + + + /** + * Returns the scale + * @returns {Number} + */ + Network.prototype.getScale = function () { + return this._getScale(); + }; + + + /** + * Returns the scale + * @returns {Number} + */ + Network.prototype.getCenterCoordinates = function () { + return this.DOMtoCanvas({x: 0.5 * this.frame.canvas.clientWidth, y: 0.5 * this.frame.canvas.clientHeight}); + }; + + + Network.prototype.getBoundingBox = function(nodeId) { + if (this.nodes[nodeId] !== undefined) { + return this.nodes[nodeId].boundingBox; + } + } + + Network.prototype.getConnectedNodes = function(nodeId) { + var nodeList = []; + if (this.nodes[nodeId] !== undefined) { + var node = this.nodes[nodeId]; + var nodeObj = {nodeId : true}; // used to quickly check if node already exists + for (var i = 0; i < node.edges.length; i++) { + var edge = node.edges[i]; + if (edge.toId == nodeId) { + if (nodeObj[edge.fromId] === undefined) { + nodeList.push(edge.fromId); + nodeObj[edge.fromId] = true; } - if (locale.meridiemHour != null) { - return locale.meridiemHour(hour, meridiem); - } else if (locale.isPM != null) { - // Fallback - isPm = locale.isPM(meridiem); - if (isPm && hour < 12) { - hour += 12; - } - if (!isPm && hour === 12) { - hour = 0; - } - return hour; - } else { - // thie is not supposed to happen - return hour; + } + else if (edge.fromId == nodeId) { + if (nodeObj[edge.toId] === undefined) { + nodeList.push(edge.toId) + nodeObj[edge.toId] = true; } + } } + } + return nodeList; + } - /************************************ - Constructors - ************************************/ - function Locale() { + Network.prototype.getEdgesFromNode = function(nodeId) { + var edgesList = []; + if (this.nodes[nodeId] !== undefined) { + var node = this.nodes[nodeId]; + for (var i = 0; i < node.edges.length; i++) { + edgesList.push(node.edges[i].id); } + } + return edgesList; + } - // Moment prototype object - function Moment(config, skipOverflow) { - if (skipOverflow !== false) { - checkOverflow(config); - } - copyConfig(this, config); - this._d = new Date(+config._d); - // Prevent infinite loop in case updateOffset creates new moment - // objects. - if (updateInProgress === false) { - updateInProgress = true; - moment.updateOffset(this); - updateInProgress = false; - } - } + Network.prototype.generateColorObject = function(color) { + return util.parseColor(color); - // 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; + module.exports = Network; - this._data = {}; - this._locale = moment.localeData(); +/***/ }, +/* 52 */ +/***/ function(module, exports, __webpack_require__) { - this._bubble(); - } + /** + * 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(); + } - /************************************ - Helpers - ************************************/ + // 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, - function extend(a, b) { - for (var i in b) { - if (hasOwnProp(b, i)) { - a[i] = b[i]; - } - } + '->': true, + '--': true + }; - if (hasOwnProp(b, 'toString')) { - a.toString = b.toString; - } + 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 - if (hasOwnProp(b, 'valueOf')) { - a.valueOf = b.valueOf; - } + /** + * 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); + } - return a; + /** + * 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); + } + + /** + * 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 (b) { + for (var name in b) { + if (b.hasOwnProperty(name)) { + a[name] = b[name]; + } } + } + return a; + } - function copyConfig(to, from) { - var i, prop, val; + /** + * 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; + } + } + } - if (typeof from._isAMomentObject !== 'undefined') { - to._isAMomentObject = from._isAMomentObject; - } - if (typeof from._i !== 'undefined') { - to._i = from._i; - } - if (typeof from._f !== 'undefined') { - to._f = from._f; - } - if (typeof from._l !== 'undefined') { - to._l = from._l; - } - if (typeof from._strict !== 'undefined') { - to._strict = from._strict; - } - if (typeof from._tzm !== 'undefined') { - to._tzm = from._tzm; - } - if (typeof from._isUTC !== 'undefined') { - to._isUTC = from._isUTC; - } - if (typeof from._offset !== 'undefined') { - to._offset = from._offset; - } - if (typeof from._pf !== 'undefined') { - to._pf = from._pf; - } - if (typeof from._locale !== 'undefined') { - to._locale = from._locale; - } + /** + * Add a node to a graph object. If there is already a node with + * the same id, their attributes will be merged. + * @param {Object} graph + * @param {Object} node + */ + function addNode(graph, node) { + var i, len; + var current = null; - if (momentProperties.length > 0) { - for (i in momentProperties) { - prop = momentProperties[i]; - val = from[prop]; - if (typeof val !== 'undefined') { - to[prop] = val; - } - } - } + // 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; + } - return to; + // 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; + } } + } - function absRound(number) { - if (number < 0) { - return Math.ceil(number); - } else { - return Math.floor(number); - } + if (!current) { + // this is a new node + current = { + id: node.id + }; + if (graph.node) { + // clone default attributes + current.attr = merge(current.attr, graph.node); } + } - // left zero fill a number - // see http://jsperf.com/left-zero-filling for performance comparison - function leftZeroFill(number, targetLength, forceSign) { - var output = '' + Math.abs(number), - sign = number >= 0; + // add node to this (sub)graph and all its parent graphs + for (i = graphs.length - 1; i >= 0; i--) { + var g = graphs[i]; - while (output.length < targetLength) { - output = '0' + output; - } - return (sign ? (forceSign ? '+' : '') : '-') + output; + if (!g.nodes) { + g.nodes = []; } + if (g.nodes.indexOf(current) == -1) { + g.nodes.push(current); + } + } - function positiveMomentsDifference(base, other) { - var res = {milliseconds: 0, months: 0}; - - res.months = other.month() - base.month() + - (other.year() - base.year()) * 12; - if (base.clone().add(res.months, 'M').isAfter(other)) { - --res.months; - } + // merge attributes + if (node.attr) { + current.attr = merge(current.attr, node.attr); + } + } - res.milliseconds = +other - +(base.clone().add(res.months, 'M')); + /** + * Add an edge to a graph object + * @param {Object} graph + * @param {Object} edge + */ + function addEdge(graph, edge) { + if (!graph.edges) { + graph.edges = []; + } + graph.edges.push(edge); + if (graph.edge) { + var attr = merge({}, graph.edge); // clone default attributes + edge.attr = merge(attr, edge.attr); // merge attributes + } + } - return res; - } + /** + * Create an edge to a graph object + * @param {Object} graph + * @param {String | Number | Object} from + * @param {String | Number | Object} to + * @param {String} type + * @param {Object | null} attr + * @return {Object} edge + */ + function createEdge(graph, from, to, type, attr) { + var edge = { + from: from, + to: to, + type: type + }; - function momentsDifference(base, other) { - var res; - other = makeAs(other, base); - if (base.isBefore(other)) { - res = positiveMomentsDifference(base, other); - } else { - res = positiveMomentsDifference(other, base); - res.milliseconds = -res.milliseconds; - res.months = -res.months; - } + if (graph.edge) { + edge.attr = merge({}, graph.edge); // clone default attributes + } + edge.attr = merge(edge.attr || {}, attr); // merge attributes - return res; - } + return edge; + } - // TODO: remove 'name' arg after deprecation is removed - function createAdder(direction, name) { - return function (val, period) { - var dur, tmp; - //invert the arguments, but complain about it - if (period !== null && !isNaN(+period)) { - deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period).'); - tmp = val; val = period; period = tmp; - } + /** + * Get next token in the current dot file. + * The token and token type are available as token and tokenType + */ + function getToken() { + tokenType = TOKENTYPE.NULL; + token = ''; - val = typeof val === 'string' ? +val : val; - dur = moment.duration(val, period); - addOrSubtractDurationFromMoment(this, dur, direction); - return this; - }; - } + // skip over whitespaces + while (c == ' ' || c == '\t' || c == '\n' || c == '\r') { // space, tab, enter + next(); + } - function addOrSubtractDurationFromMoment(mom, duration, isAdding, updateOffset) { - var milliseconds = duration._milliseconds, - days = duration._days, - months = duration._months; - updateOffset = updateOffset == null ? true : updateOffset; + do { + var isComment = false; - if (milliseconds) { - mom._d.setTime(+mom._d + milliseconds * isAdding); - } - if (days) { - rawSetter(mom, 'Date', rawGetter(mom, 'Date') + days * isAdding); + // 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(); } - if (months) { - rawMonthSetter(mom, rawGetter(mom, 'Month') + months * isAdding); + isComment = true; + } + } + if (c == '/' && nextPreview() == '/') { + // skip line comment + while (c != '' && c != '\n') { + next(); + } + isComment = true; + } + if (c == '/' && nextPreview() == '*') { + // skip block comment + while (c != '') { + if (c == '*' && nextPreview() == '/') { + // end of block comment found. skip these last two characters + next(); + next(); + break; } - if (updateOffset) { - moment.updateOffset(mom, days || months); + else { + next(); } + } + isComment = true; } - // check if is an array - function isArray(input) { - return Object.prototype.toString.call(input) === '[object Array]'; + // skip over whitespaces + while (c == ' ' || c == '\t' || c == '\n' || c == '\r') { // space, tab, enter + next(); } + } + while (isComment); - function isDate(input) { - return Object.prototype.toString.call(input) === '[object Date]' || - input instanceof Date; - } + // check for end of dot file + if (c == '') { + // token is still empty + tokenType = TOKENTYPE.DELIMITER; + return; + } - // 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; - } + // check for delimiters consisting of 2 characters + var c2 = c + nextPreview(); + if (DELIMITERS[c2]) { + tokenType = TOKENTYPE.DELIMITER; + token = c2; + next(); + next(); + return; + } - function normalizeUnits(units) { - if (units) { - var lowered = units.toLowerCase().replace(/(.)s$/, '$1'); - units = unitAliases[units] || camelFunctions[lowered] || lowered; - } - return units; - } + // check for delimiters consisting of 1 character + if (DELIMITERS[c]) { + tokenType = TOKENTYPE.DELIMITER; + token = c; + next(); + return; + } - function normalizeObjectUnits(inputObject) { - var normalizedInput = {}, - normalizedProp, - prop; + // 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(); - for (prop in inputObject) { - if (hasOwnProp(inputObject, prop)) { - normalizedProp = normalizeUnits(prop); - if (normalizedProp) { - normalizedInput[normalizedProp] = inputObject[prop]; - } - } - } + 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; + } - return normalizedInput; + // 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; + } - function makeList(field) { - var count, setter; + // 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) + '"'); + } - if (field.indexOf('week') === 0) { - count = 7; - setter = 'day'; - } - else if (field.indexOf('month') === 0) { - count = 12; - setter = 'month'; - } - else { - return; - } + /** + * Parse a graph. + * @returns {Object} graph + */ + function parseGraph() { + var graph = {}; - moment[field] = function (format, index) { - var i, getter, - method = moment._locale[field], - results = []; + first(); + getToken(); - if (typeof format === 'number') { - index = format; - format = undefined; - } + // optional strict keyword + if (token == 'strict') { + graph.strict = true; + getToken(); + } - getter = function (i) { - var m = moment().utc().set(setter, i); - return method.call(moment._locale, m, format || ''); - }; + // graph or digraph keyword + if (token == 'graph' || token == 'digraph') { + graph.type = token; + getToken(); + } - if (index != null) { - return getter(index); - } - else { - for (i = 0; i < count; i++) { - results.push(getter(i)); - } - return results; - } - }; - } + // optional graph id + if (tokenType == TOKENTYPE.IDENTIFIER) { + graph.id = token; + getToken(); + } - function toInt(argumentForCoercion) { - var coercedNumber = +argumentForCoercion, - value = 0; + // open angle bracket + if (token != '{') { + throw newSyntaxError('Angle bracket { expected'); + } + getToken(); - if (coercedNumber !== 0 && isFinite(coercedNumber)) { - if (coercedNumber >= 0) { - value = Math.floor(coercedNumber); - } else { - value = Math.ceil(coercedNumber); - } - } + // statements + parseStatements(graph); - return value; - } + // close angle bracket + if (token != '}') { + throw newSyntaxError('Angle bracket } expected'); + } + getToken(); - function daysInMonth(year, month) { - return new Date(Date.UTC(year, month + 1, 0)).getUTCDate(); - } + // end of file + if (token !== '') { + throw newSyntaxError('End of file expected'); + } + getToken(); - function weeksInYear(year, dow, doy) { - return weekOfYear(moment([year, 11, 31 + dow - doy]), dow, doy).week; - } + // remove temporary default properties + delete graph.node; + delete graph.edge; + delete graph.graph; - function daysInYear(year) { - return isLeapYear(year) ? 366 : 365; - } + return graph; + } - function isLeapYear(year) { - return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; + /** + * Parse a list with statements. + * @param {Object} graph + */ + function parseStatements (graph) { + while (token !== '' && token != '}') { + parseStatement(graph); + if (token == ';') { + getToken(); } + } + } - 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] > 24 || - (m._a[HOUR] === 24 && (m._a[MINUTE] !== 0 || - m._a[SECOND] !== 0 || - m._a[MILLISECOND] !== 0)) ? 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; + /** + * 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); - if (m._pf._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) { - overflow = DATE; - } + return; + } - m._pf.overflow = overflow; - } - } + // parse an attribute statement + var attr = parseAttributeStatement(graph); + if (attr) { + return; + } - 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; + // parse node + if (tokenType != TOKENTYPE.IDENTIFIER) { + throw newSyntaxError('Identifier expected'); + } + var id = token; // id can be a string or a number + getToken(); - if (m._strict) { - m._isValid = m._isValid && - m._pf.charsLeftOver === 0 && - m._pf.unusedTokens.length === 0 && - m._pf.bigHour === undefined; - } - } - return m._isValid; + if (token == '=') { + // id statement + getToken(); + if (tokenType != TOKENTYPE.IDENTIFIER) { + throw newSyntaxError('Identifier expected'); } + graph[id] = token; + getToken(); + // TODO: implement comma separated list with "a_list: ID=ID [','] [a_list] " + } + else { + parseNodeStatement(graph, id); + } + } + + /** + * Parse a subgraph + * @param {Object} graph parent graph object + * @return {Object | null} subgraph + */ + function parseSubgraph (graph) { + var subgraph = null; - function normalizeLocale(key) { - return key ? key.toLowerCase().replace('_', '-') : key; + // optional subgraph keyword + if (token == 'subgraph') { + subgraph = {}; + subgraph.type = 'subgraph'; + getToken(); + + // optional graph id + if (tokenType == TOKENTYPE.IDENTIFIER) { + subgraph.id = token; + getToken(); } + } - // pick the locale 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 - function chooseLocale(names) { - var i = 0, j, next, locale, split; + // open angle bracket + if (token == '{') { + getToken(); - while (i < names.length) { - split = normalizeLocale(names[i]).split('-'); - j = split.length; - next = normalizeLocale(names[i + 1]); - next = next ? next.split('-') : null; - while (j > 0) { - locale = loadLocale(split.slice(0, j).join('-')); - if (locale) { - return locale; - } - 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 null; + if (!subgraph) { + subgraph = {}; } + subgraph.parent = graph; + subgraph.node = graph.node; + subgraph.edge = graph.edge; + subgraph.graph = graph.graph; - function loadLocale(name) { - var oldLocale = null; - if (!locales[name] && hasModule) { - try { - oldLocale = moment.locale(); - !(function webpackMissingModule() { var e = new Error("Cannot find module \"./locale\""); e.code = 'MODULE_NOT_FOUND'; throw e; }()); - // because defineLocale currently also sets the global locale, we want to undo that for lazy loaded locales - moment.locale(oldLocale); - } catch (e) { } - } - return locales[name]; - } + // statements + parseStatements(subgraph); - // Return a moment from input, that is local/utc/utcOffset equivalent to - // model. - function makeAs(input, model) { - var res, diff; - if (model._isUTC) { - res = model.clone(); - diff = (moment.isMoment(input) || isDate(input) ? - +input : +moment(input)) - (+res); - // Use low-level api, because this fn is low-level api. - res._d.setTime(+res._d + diff); - moment.updateOffset(res, false); - return res; - } else { - return moment(input).local(); - } + // close angle bracket + if (token != '}') { + throw newSyntaxError('Angle bracket } expected'); } + getToken(); - /************************************ - Locale - ************************************/ - + // remove temporary default properties + delete subgraph.node; + delete subgraph.edge; + delete subgraph.graph; + delete subgraph.parent; - extend(Locale.prototype, { + // register at the parent graph + if (!graph.subgraphs) { + graph.subgraphs = []; + } + graph.subgraphs.push(subgraph); + } - set : function (config) { - var prop, i; - for (i in config) { - prop = config[i]; - if (typeof prop === 'function') { - this[i] = prop; - } else { - this['_' + i] = prop; - } - } - // Lenient ordinal parsing accepts just a number in addition to - // number + (possibly) stuff coming from _ordinalParseLenient. - this._ordinalParseLenient = new RegExp(this._ordinalParse.source + '|' + /\d{1,2}/.source); - }, + return subgraph; + } - _months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), - months : function (m) { - return this._months[m.month()]; - }, + /** + * 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(); - _monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), - monthsShort : function (m) { - return this._monthsShort[m.month()]; - }, + // node attributes + graph.node = parseAttributeList(); + return 'node'; + } + else if (token == 'edge') { + getToken(); - monthsParse : function (monthName, format, strict) { - var i, mom, regex; + // edge attributes + graph.edge = parseAttributeList(); + return 'edge'; + } + else if (token == 'graph') { + getToken(); - if (!this._monthsParse) { - this._monthsParse = []; - this._longMonthsParse = []; - this._shortMonthsParse = []; - } + // graph attributes + graph.graph = parseAttributeList(); + return 'graph'; + } - for (i = 0; i < 12; i++) { - // make the regex if we don't have it already - mom = moment.utc([2000, i]); - if (strict && !this._longMonthsParse[i]) { - this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i'); - this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i'); - } - if (!strict && !this._monthsParse[i]) { - regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, ''); - this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i'); - } - // test the regex - if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) { - return i; - } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) { - return i; - } else if (!strict && this._monthsParse[i].test(monthName)) { - return i; - } - } - }, + return null; + } - _weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), - weekdays : function (m) { - return this._weekdays[m.day()]; - }, + /** + * 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); - _weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), - weekdaysShort : function (m) { - return this._weekdaysShort[m.day()]; - }, + // edge statements + parseEdge(graph, id); + } - _weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), - weekdaysMin : function (m) { - return this._weekdaysMin[m.day()]; - }, + /** + * 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(); - weekdaysParse : function (weekdayName) { - var i, mom, regex; + 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(); + } - if (!this._weekdaysParse) { - this._weekdaysParse = []; - } + // parse edge attributes + var attr = parseAttributeList(); - 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; - } - } - }, + // create edge + var edge = createEdge(graph, from, to, type, attr); + addEdge(graph, edge); - _longDateFormat : { - LTS : 'h:mm:ss A', - 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; - }, + from = to; + } + } - 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'); - }, + /** + * Parse a set with attributes, + * for example [label="1.000", shape=solid] + * @return {Object | null} attr + */ + function parseAttributeList() { + var attr = null; - _meridiemParse : /[ap]\.?m?\.?/i, - meridiem : function (hours, minutes, isLower) { - if (hours > 11) { - return isLower ? 'pm' : 'PM'; - } else { - return isLower ? 'am' : 'AM'; - } - }, + while (token == '[') { + getToken(); + attr = {}; + while (token !== '' && token != ']') { + if (tokenType != TOKENTYPE.IDENTIFIER) { + throw newSyntaxError('Attribute name expected'); + } + var name = token; + getToken(); + if (token != '=') { + throw newSyntaxError('Equal sign = expected'); + } + getToken(); - _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, now) { - var output = this._calendar[key]; - return typeof output === 'function' ? output.apply(mom, [now]) : output; - }, + if (tokenType != TOKENTYPE.IDENTIFIER) { + throw newSyntaxError('Attribute value expected'); + } + var value = token; + setValue(attr, name, value); // name can be a path - _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' - }, + getToken(); + if (token ==',') { + getToken(); + } + } - 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); - }, + if (token != ']') { + throw newSyntaxError('Bracket ] expected'); + } + getToken(); + } - pastFuture : function (diff, output) { - var format = this._relativeTime[diff > 0 ? 'future' : 'past']; - return typeof format === 'function' ? format(output) : format.replace(/%s/i, output); - }, + return attr; + } - ordinal : function (number) { - return this._ordinal.replace('%d', number); - }, - _ordinal : '%d', - _ordinalParse : /\d{1,2}/, + /** + * 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 + ')'); + } - preparse : function (string) { - return string; - }, + /** + * 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) + '...'); + } - postformat : function (string) { - return string; - }, + /** + * 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 (Array.isArray(array1)) { + array1.forEach(function (elem1) { + if (Array.isArray(array2)) { + array2.forEach(function (elem2) { + fn(elem1, elem2); + }); + } + else { + fn(elem1, array2); + } + }); + } + else { + if (Array.isArray(array2)) { + array2.forEach(function (elem2) { + fn(array1, elem2); + }); + } + else { + fn(array1, array2); + } + } + } - week : function (mom) { - return weekOfYear(mom, this._week.dow, this._week.doy).week; - }, + /** + * 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: {} + }; - _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. - }, + // 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); + }); + } - firstDayOfWeek : function () { - return this._week.dow; - }, + // copy the edges + if (dotData.edges) { + /** + * Convert an edge in DOT format to an edge with VisGraph format + * @param {Object} dotEdge + * @returns {Object} graphEdge + */ + var convertEdge = function (dotEdge) { + var graphEdge = { + from: dotEdge.from, + to: dotEdge.to + }; + merge(graphEdge, dotEdge.attr); + graphEdge.style = (dotEdge.type == '->') ? 'arrow' : 'line'; + return graphEdge; + } - firstDayOfYear : function () { - return this._week.doy; - }, + dotData.edges.forEach(function (dotEdge) { + var from, to; + if (dotEdge.from instanceof Object) { + from = dotEdge.from.nodes; + } + else { + from = { + id: dotEdge.from + } + } - _invalidDate: 'Invalid date', - invalidDate: function () { - return this._invalidDate; + if (dotEdge.to instanceof Object) { + to = dotEdge.to.nodes; + } + else { + to = { + id: dotEdge.to } + } + + if (dotEdge.from instanceof Object && dotEdge.from.edges) { + dotEdge.from.edges.forEach(function (subEdge) { + var graphEdge = convertEdge(subEdge); + graphData.edges.push(graphEdge); + }); + } + + forEach2(from, to, function (from, to) { + var subEdge = createEdge(graphData, from.id, to.id, dotEdge.type, dotEdge.attr); + var graphEdge = convertEdge(subEdge); + graphData.edges.push(graphEdge); + }); + + if (dotEdge.to instanceof Object && dotEdge.to.edges) { + dotEdge.to.edges.forEach(function (subEdge) { + var graphEdge = convertEdge(subEdge); + graphData.edges.push(graphEdge); + }); + } }); + } - /************************************ - Formatting - ************************************/ + // copy the options + if (dotData.attr) { + graphData.options = dotData.attr; + } + return graphData; + } - function removeFormattingTokens(input) { - if (input.match(/\[[\s\S]/)) { - return input.replace(/^\[|\]$/g, ''); - } - return input.replace(/\\/g, ''); - } + // exports + exports.parseDOT = parseDOT; + exports.DOTToGraph = DOTToGraph; - function makeFormatFunction(format) { - var array = format.match(formattingTokens), i, length; - for (i = 0, length = array.length; i < length; i++) { - if (formatTokenFunctions[array[i]]) { - array[i] = formatTokenFunctions[array[i]]; - } else { - array[i] = removeFormattingTokens(array[i]); - } - } +/***/ }, +/* 53 */ +/***/ function(module, exports, __webpack_require__) { - 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; - }; + + function parseGephi(gephiJSON, options) { + var edges = []; + var nodes = []; + this.options = { + edges: { + inheritColor: true + }, + nodes: { + allowedToMove: false, + parseColor: false } + }; - // format date using native date object - function formatMoment(m, format) { - if (!m.isValid()) { - return m.localeData().invalidDate(); - } - - format = expandFormat(format, m.localeData()); + 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 (!formatFunctions[format]) { - formatFunctions[format] = makeFormatFunction(format); - } + 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); + } - return formatFunctions[format](m); + 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); + } - function expandFormat(format, locale) { - var i = 5; - - function replaceLongDateFormatTokens(input) { - return locale.longDateFormat(input) || input; - } + return {nodes:nodes, edges:edges}; + } - localFormattingTokens.lastIndex = 0; - while (i >= 0 && localFormattingTokens.test(format)) { - format = format.replace(localFormattingTokens, replaceLongDateFormatTokens); - localFormattingTokens.lastIndex = 0; - i -= 1; - } + exports.parseGephi = parseGephi; - return format; - } +/***/ }, +/* 54 */ +/***/ function(module, exports, __webpack_require__) { + var util = __webpack_require__(1); - /************************************ - Parsing - ************************************/ + /** + * @class Groups + * This class can store groups and properties specific for groups. + */ + function Groups() { + this.clear(); + this.defaultIndex = 0; + this.groupsArray = []; + this.groupIndex = 0; + this.useDefaultGroups = true; + } - // get the regex to find the next token - function getParseRegexForToken(token, config) { - var a, strict = config._strict; - switch (token) { - case 'Q': - return parseTokenOneDigit; - case 'DDDD': - return parseTokenThreeDigits; - case 'YYYY': - case 'GGGG': - case 'gggg': - return strict ? parseTokenFourDigits : parseTokenOneToFourDigits; - case 'Y': - case 'G': - case 'g': - return parseTokenSignedNumber; - case 'YYYYYY': - case 'YYYYY': - case 'GGGGG': - case 'ggggg': - return strict ? parseTokenSixDigits : parseTokenOneToSixDigits; - case 'S': - if (strict) { - return parseTokenOneDigit; - } - /* falls through */ - case 'SS': - if (strict) { - return parseTokenTwoDigits; - } - /* falls through */ - case 'SSS': - if (strict) { - return parseTokenThreeDigits; - } - /* falls through */ - case 'DDD': - return parseTokenOneToThreeDigits; - case 'MMM': - case 'MMMM': - case 'dd': - case 'ddd': - case 'dddd': - return parseTokenWord; - case 'a': - case 'A': - return config._locale._meridiemParse; - case 'x': - return parseTokenOffsetMs; - 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 strict ? config._locale._ordinalParse : config._locale._ordinalParseLenient; - default : - a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), 'i')); - return a; - } - } + /** + * default constants for group colors + */ + Groups.DEFAULT = [ + {border: "#2B7CE9", background: "#97C2FC", highlight: {border: "#2B7CE9", background: "#D2E5FF"}, hover: {border: "#2B7CE9", background: "#D2E5FF"}}, // 0: blue + {border: "#FFA500", background: "#FFFF00", highlight: {border: "#FFA500", background: "#FFFFA3"}, hover: {border: "#FFA500", background: "#FFFFA3"}}, // 1: yellow + {border: "#FA0A10", background: "#FB7E81", highlight: {border: "#FA0A10", background: "#FFAFB1"}, hover: {border: "#FA0A10", background: "#FFAFB1"}}, // 2: red + {border: "#41A906", background: "#7BE141", highlight: {border: "#41A906", background: "#A1EC76"}, hover: {border: "#41A906", background: "#A1EC76"}}, // 3: green + {border: "#E129F0", background: "#EB7DF4", highlight: {border: "#E129F0", background: "#F0B3F5"}, hover: {border: "#E129F0", background: "#F0B3F5"}}, // 4: magenta + {border: "#7C29F0", background: "#AD85E4", highlight: {border: "#7C29F0", background: "#D3BDF0"}, hover: {border: "#7C29F0", background: "#D3BDF0"}}, // 5: purple + {border: "#C37F00", background: "#FFA807", highlight: {border: "#C37F00", background: "#FFCA66"}, hover: {border: "#C37F00", background: "#FFCA66"}}, // 6: orange + {border: "#4220FB", background: "#6E6EFD", highlight: {border: "#4220FB", background: "#9B9BFD"}, hover: {border: "#4220FB", background: "#9B9BFD"}}, // 7: darkblue + {border: "#FD5A77", background: "#FFC0CB", highlight: {border: "#FD5A77", background: "#FFD1D9"}, hover: {border: "#FD5A77", background: "#FFD1D9"}}, // 8: pink + {border: "#4AD63A", background: "#C2FABC", highlight: {border: "#4AD63A", background: "#E6FFE3"}, hover: {border: "#4AD63A", background: "#E6FFE3"}}, // 9: mint - function utcOffsetFromString(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]); + {border: "#990000", background: "#EE0000", highlight: {border: "#BB0000", background: "#FF3333"}, hover: {border: "#BB0000", background: "#FF3333"}}, // 10:bright red - return parts[0] === '+' ? minutes : -minutes; - } + {border: "#FF6000", background: "#FF6000", highlight: {border: "#FF6000", background: "#FF6000"}, hover: {border: "#FF6000", background: "#FF6000"}}, // 12: real orange + {border: "#97C2FC", background: "#2B7CE9", highlight: {border: "#D2E5FF", background: "#2B7CE9"}, hover: {border: "#D2E5FF", background: "#2B7CE9"}}, // 13: blue + {border: "#399605", background: "#255C03", highlight: {border: "#399605", background: "#255C03"}, hover: {border: "#399605", background: "#255C03"}}, // 14: green + {border: "#B70054", background: "#FF007E", highlight: {border: "#B70054", background: "#FF007E"}, hover: {border: "#B70054", background: "#FF007E"}}, // 15: magenta + {border: "#AD85E4", background: "#7C29F0", highlight: {border: "#D3BDF0", background: "#7C29F0"}, hover: {border: "#D3BDF0", background: "#7C29F0"}}, // 16: purple + {border: "#4557FA", background: "#000EA1", highlight: {border: "#6E6EFD", background: "#000EA1"}, hover: {border: "#6E6EFD", background: "#000EA1"}}, // 17: darkblue + {border: "#FFC0CB", background: "#FD5A77", highlight: {border: "#FFD1D9", background: "#FD5A77"}, hover: {border: "#FFD1D9", background: "#FD5A77"}}, // 18: pink + {border: "#C2FABC", background: "#74D66A", highlight: {border: "#E6FFE3", background: "#74D66A"}, hover: {border: "#E6FFE3", background: "#74D66A"}}, // 19: mint - // function to convert string input to date - function addTimeToArrayFromToken(token, input, config) { - var a, datePartArray = config._a; + {border: "#EE0000", background: "#990000", highlight: {border: "#FF3333", background: "#BB0000"}, hover: {border: "#FF3333", background: "#BB0000"}}, // 20:bright red + ]; - 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 = config._locale.monthsParse(input, token, config._strict); - // 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.match(/\d{1,2}/)[0], 10)); - } - break; - // DAY OF YEAR - case 'DDD' : // fall through to DDDD - case 'DDDD' : - if (input != null) { - config._dayOfYear = toInt(input); - } - 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._meridiem = input; - // config._isPm = config._locale.isPM(input); - break; - // HOUR - case 'h' : // fall through to hh - case 'hh' : - config._pf.bigHour = true; - /* falls through */ - 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 OFFSET (MILLISECONDS) - case 'x': - config._d = new Date(toInt(input)); - 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 = utcOffsetFromString(input); - break; - // WEEKDAY - human - case 'dd': - case 'ddd': - case 'dddd': - a = config._locale.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); - } + /** + * 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; + } + }; - function dayOfYearFromWeekInfo(config) { - var w, weekYear, week, weekday, dow, doy, temp; - - w = config._w; - if (w.GG != null || w.W != null || w.E != null) { - dow = 1; - doy = 4; - // 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 { - dow = config._locale._week.dow; - doy = config._locale._week.doy; + /** + * 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) { + if (this.useDefaultGroups === false && this.groupsArray.length > 0) { + // create new group + var index = this.groupIndex % this.groupsArray.length; + this.groupIndex++; + group = {}; + group.color = this.groups[this.groupsArray[index]]; + this.groups[groupname] = group; + } + else { + // create new group + var index = this.defaultIndex % Groups.DEFAULT.length; + this.defaultIndex++; + group = {}; + group.color = Groups.DEFAULT[index]; + this.groups[groupname] = group; + } + } - weekYear = dfl(w.gg, config._a[YEAR], weekOfYear(moment(), dow, doy).year); - week = dfl(w.w, 1); + return group; + }; - 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); + /** + * 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; + this.groupsArray.push(groupName); + return style; + }; - config._a[YEAR] = temp.year; - config._dayOfYear = temp.dayOfYear; - } + module.exports = Groups; - // 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; - } +/***/ }, +/* 55 */ +/***/ function(module, exports, __webpack_require__) { - currentDate = currentDateArray(config); + /** + * @class Images + * This class loads images and keeps them stored. + */ + function Images() { + this.images = {}; + this.imageBroken = {}; + this.callback = undefined; + } - //compute day of the year from weeks and weekdays - if (config._w && config._a[DATE] == null && config._a[MONTH] == null) { - dayOfYearFromWeekInfo(config); - } + /** + * 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; + }; - //if the day of the year is set, figure out what it is - if (config._dayOfYear) { - yearToUse = dfl(config._a[YEAR], currentDate[YEAR]); + /** + * + * @param {string} url Url of the image + * @param {string} url Url of an image to use if the url image is not found + * @return {Image} img The image object + */ + Images.prototype.load = function(url, brokenUrl) { + var img = this.images[url]; // make a pointer + if (img === undefined) { + // create the image + var me = this; + img = new Image(); + img.onload = function () { + // IE11 fix -- thanks dponch! + if (this.width == 0) { + document.body.appendChild(this); + this.width = this.offsetWidth; + this.height = this.offsetHeight; + document.body.removeChild(this); + } - if (config._dayOfYear > daysInYear(yearToUse)) { - config._pf._overflowDayOfYear = true; - } + if (me.callback) { + me.images[url] = img; + me.callback(this); + } + }; - date = makeUTCDate(yearToUse, 0, config._dayOfYear); - config._a[MONTH] = date.getUTCMonth(); - config._a[DATE] = date.getUTCDate(); + img.onerror = function () { + if (brokenUrl === undefined) { + console.error("Could not load image:", url); + delete this.src; + if (me.callback) { + me.callback(this); } - - // 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]; + } + else { + if (me.imageBroken[url] === true) { + if (this.src == brokenUrl) { + console.error("Could not load brokenImage:", brokenUrl); + delete this.src; + if (me.callback) { + me.callback(this); + } + } + else { + console.error("Could not load image:", url); + this.src = brokenUrl; + } } - - // 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 { + console.error("Could not load image:", url); + this.src = brokenUrl; + me.imageBroken[url] = true; } + } + }; - // Check for 24:00:00.000 - if (config._a[HOUR] === 24 && - config._a[MINUTE] === 0 && - config._a[SECOND] === 0 && - config._a[MILLISECOND] === 0) { - config._nextDay = true; - config._a[HOUR] = 0; - } + img.src = url; + } - config._d = (config._useUTC ? makeUTCDate : makeDate).apply(null, input); - // Apply timezone offset from input. The actual utcOffset can be changed - // with parseZone. - if (config._tzm != null) { - config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm); - } + return img; + }; - if (config._nextDay) { - config._a[HOUR] = 24; - } - } + module.exports = Images; - function dateFromObject(config) { - var normalizedInput; - if (config._d) { - return; - } +/***/ }, +/* 56 */ +/***/ function(module, exports, __webpack_require__) { - normalizedInput = normalizeObjectUnits(config._i); - config._a = [ - normalizedInput.year, - normalizedInput.month, - normalizedInput.day || normalizedInput.date, - normalizedInput.hour, - normalizedInput.minute, - normalizedInput.second, - normalizedInput.millisecond - ]; + var util = __webpack_require__(1); - dateFromConfig(config); - } + /** + * @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", "icon" + * {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, networkConstants) { + var constants = util.selectiveBridgeObject(['nodes'],networkConstants); + this.options = constants.nodes; - 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()]; - } - } + this.selected = false; + this.hover = false; - // date from string and format string - function makeDateFromStringAndFormat(config) { - if (config._f === moment.ISO_8601) { - parseISO(config); - return; - } + this.edges = []; // all edges connected to this node - config._a = []; - config._pf.empty = true; + // set defaults for the properties + this.id = undefined; + this.allowedToMoveX = false; + this.allowedToMoveY = false; + this.xFixed = false; + this.yFixed = false; + this.horizontalAlignLeft = true; // these are for the navigation controls + this.verticalAlignTop = true; // these are for the navigation controls + this.baseRadiusValue = networkConstants.nodes.radius; + this.radiusFixed = false; + this.level = -1; + this.preassignedLevel = false; + this.hierarchyEnumerated = false; + this.labelDimensions = {top:0, left:0, width:0, height:0, yLine:0}; // could be cached + this.boundingBox = {top:0, left:0, right:0, bottom:0}; - // This array is used to make a Date, either with `new Date` or `Date.UTC` - var string = '' + config._i, - i, parsedInput, tokens, token, skipped, - stringLength = string.length, - totalParsedInputLength = 0; + this.imagelist = imagelist; + this.grouplist = grouplist; - tokens = expandFormat(config._f, config._locale).match(formattingTokens) || []; + // 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.x = null; + this.y = null; + this.predefinedPosition = false; // used to check if initial zoomExtent should just take the range or approximate - 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); - } - } + // used for reverting to previous position on stabilization + this.previousState = {vx:0,vy:0,x:0,y:0}; - // add remaining unparsed input length to the string - config._pf.charsLeftOver = stringLength - totalParsedInputLength; - if (string.length > 0) { - config._pf.unusedInput.push(string); - } + this.damping = networkConstants.physics.damping; // written every time gravity is calculated + this.fixedData = {x:null,y:null}; - // clear _12h flag if hour is <= 12 - if (config._pf.bigHour === true && config._a[HOUR] <= 12) { - config._pf.bigHour = undefined; - } - // handle meridiem - config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], - config._meridiem); - dateFromConfig(config); - checkOverflow(config); - } + this.setProperties(properties, constants); - function unescapeFormat(s) { - return s.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) { - return p1 || p2 || p3 || p4; - }); - } + // 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; + } - // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript - function regexpEscape(s) { - return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); - } - // date from string and array of format strings - function makeDateFromStringAndArray(config) { - var tempConfig, - bestMoment, + /** + * Revert the position and velocity of the previous step. + */ + Node.prototype.revertPosition = function() { + this.x = this.previousState.x; + this.y = this.previousState.y; + this.vx = this.previousState.vx; + this.vy = this.previousState.vy; + } - scoreToBeat, - i, - currentScore; - if (config._f.length === 0) { - config._pf.invalidFormat = true; - config._d = new Date(NaN); - return; - } + /** + * Attach a edge to the node + * @param {Edge} edge + */ + Node.prototype.attachEdge = function(edge) { + if (this.edges.indexOf(edge) == -1) { + this.edges.push(edge); + } + }; - for (i = 0; i < config._f.length; i++) { - currentScore = 0; - tempConfig = copyConfig({}, config); - if (config._useUTC != null) { - tempConfig._useUTC = config._useUTC; - } - tempConfig._pf = defaultParsingFlags(); - tempConfig._f = config._f[i]; - makeDateFromStringAndFormat(tempConfig); + /** + * 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); + } + }; - if (!isValid(tempConfig)) { - continue; - } - // if there is any input that was not parsed add a penalty for that format - currentScore += tempConfig._pf.charsLeftOver; + /** + * 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.properties = properties; - //or tokens - currentScore += tempConfig._pf.unusedTokens.length * 10; + var fields = ['borderWidth', 'borderWidthSelected', 'shape', 'image', 'brokenImage', 'radius', 'fontColor', + 'fontSize', 'fontFace', 'fontFill', 'fontStrokeWidth', 'fontStrokeColor', 'group', 'mass', 'fontDrawThreshold', + 'scaleFontWithValue', 'fontSizeMaxVisible', 'customScalingFunction', 'iconFontFace', 'icon', 'iconColor', 'iconSize', + 'value' + ]; + util.selectiveDeepExtend(fields, this.options, properties); - tempConfig._pf.score = currentScore; + // basic properties + if (properties.id !== undefined) {this.id = properties.id;} + if (properties.label !== undefined) {this.label = properties.label; this.originalLabel = properties.label;} + if (properties.title !== undefined) {this.title = properties.title;} + if (properties.x !== undefined) {this.x = properties.x; this.predefinedPosition = true;} + if (properties.y !== undefined) {this.y = properties.y; this.predefinedPosition = true;} + if (properties.value !== undefined) {this.value = properties.value;} + if (properties.level !== undefined) {this.level = properties.level; this.preassignedLevel = true;} - if (scoreToBeat == null || currentScore < scoreToBeat) { - scoreToBeat = currentScore; - bestMoment = tempConfig; - } - } + // 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;} - extend(config, bestMoment || tempConfig); - } + if (this.id === undefined) { + throw "Node must have an id"; + } - // date from iso format - function parseISO(config) { - var i, l, - string = config._i, - match = isoRegex.exec(string); + // copy group properties + if (typeof properties.group === 'number' || (typeof properties.group === 'string' && properties.group != '')) { + var groupObj = this.grouplist.get(properties.group); + util.deepExtend(this.options, groupObj); + // the color object needs to be completely defined. Since groups can partially overwrite the colors, we parse it again, just in case. + this.options.color = util.parseColor(this.options.color); + } + // individual shape properties + if (properties.radius !== undefined) {this.baseRadiusValue = this.options.radius;} + if (properties.color !== undefined) {this.options.color = util.parseColor(properties.color);} - if (match) { - config._pf.iso = true; - for (i = 0, l = isoDates.length; i < l; i++) { - if (isoDates[i][1].exec(string)) { - // match[5] should be 'T' or undefined - config._f = isoDates[i][0] + (match[6] || ' '); - break; - } - } - for (i = 0, l = isoTimes.length; i < l; i++) { - if (isoTimes[i][1].exec(string)) { - config._f += isoTimes[i][0]; - break; - } - } - if (string.match(parseTokenTimezone)) { - config._f += 'Z'; - } - makeDateFromStringAndFormat(config); - } else { - config._isValid = false; - } + if (this.options.image !== undefined && this.options.image!= "") { + if (this.imagelist) { + this.imageObj = this.imagelist.load(this.options.image, this.options.brokenImage); } - - // date from iso format or fallback - function makeDateFromString(config) { - parseISO(config); - if (config._isValid === false) { - delete config._isValid; - moment.createFromInputFallback(config); - } + else { + throw "No imagelist provided"; } + } - function map(arr, fn) { - var res = [], i; - for (i = 0; i < arr.length; ++i) { - res.push(fn(arr[i], i)); - } - return res; - } + if (properties.allowedToMoveX !== undefined) { + this.xFixed = !properties.allowedToMoveX; + this.allowedToMoveX = properties.allowedToMoveX; + } + else if (properties.x !== undefined && this.allowedToMoveX == false) { + this.xFixed = true; + } - function makeDateFromInput(config) { - var input = config._i, matched; - if (input === undefined) { - config._d = new Date(); - } else if (isDate(input)) { - config._d = new Date(+input); - } else if ((matched = aspNetJsonRegex.exec(input)) !== null) { - config._d = new Date(+matched[1]); - } else if (typeof input === 'string') { - makeDateFromString(config); - } else if (isArray(input)) { - config._a = map(input.slice(0), function (obj) { - return parseInt(obj, 10); - }); - dateFromConfig(config); - } 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); + if (properties.allowedToMoveY !== undefined) { + this.yFixed = !properties.allowedToMoveY; + this.allowedToMoveY = properties.allowedToMoveY; + } + else if (properties.y !== undefined && this.allowedToMoveY == false) { + this.yFixed = true; + } - //the date constructor doesn't accept years < 1970 - if (y < 1970) { - date.setFullYear(y); - } - return date; - } + this.radiusFixed = this.radiusFixed || (properties.radius !== undefined); - function makeUTCDate(y) { - var date = new Date(Date.UTC.apply(null, arguments)); - if (y < 1970) { - date.setUTCFullYear(y); - } - return date; - } + if (this.options.shape === 'image' || this.options.shape === 'circularImage') { + this.options.radiusMin = constants.nodes.widthMin; + this.options.radiusMax = constants.nodes.widthMax; + } - function parseWeekday(input, locale) { - if (typeof input === 'string') { - if (!isNaN(input)) { - input = parseInt(input, 10); - } - else { - input = locale.weekdaysParse(input); - if (typeof input !== 'number') { - return null; - } - } - } - return input; - } + // choose draw method depending on the shape + switch (this.options.shape) { + case 'database': this.draw = this._drawDatabase; this.resize = this._resizeDatabase; break; + case 'box': this.draw = this._drawBox; this.resize = this._resizeBox; break; + case 'circle': this.draw = this._drawCircle; this.resize = this._resizeCircle; break; + case 'ellipse': this.draw = this._drawEllipse; this.resize = this._resizeEllipse; break; + // TODO: add diamond shape + case 'image': this.draw = this._drawImage; this.resize = this._resizeImage; break; + case 'circularImage': this.draw = this._drawCircularImage; this.resize = this._resizeCircularImage; 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; + case 'icon': this.draw = this._drawIcon; this.resize = this._resizeIcon; break; + default: this.draw = this._drawEllipse; this.resize = this._resizeEllipse; break; + } + // reset the size of the node, this can be changed + this._reset(); - /************************************ - Relative Time - ************************************/ + }; + /** + * select this node + */ + Node.prototype.select = function() { + this.selected = true; + this._reset(); + }; - // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize - function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) { - return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture); - } + /** + * unselect this node + */ + Node.prototype.unselect = function() { + this.selected = false; + this._reset(); + }; - function relativeTime(posNegDuration, withoutSuffix, locale) { - var duration = moment.duration(posNegDuration).abs(), - seconds = round(duration.as('s')), - minutes = round(duration.as('m')), - hours = round(duration.as('h')), - days = round(duration.as('d')), - months = round(duration.as('M')), - years = round(duration.as('y')), - 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.d && ['dd', days] || - months === 1 && ['M'] || - months < relativeTimeThresholds.M && ['MM', months] || - years === 1 && ['y'] || ['yy', years]; + /** + * Reset the calculated size of the node, forces it to recalculate its size + */ + Node.prototype.clearSizeCache = function() { + this._reset(); + }; - args[2] = withoutSuffix; - args[3] = +posNegDuration > 0; - args[4] = locale; - return substituteTimeAgo.apply({}, args); - } + /** + * Reset the calculated size of the node, forces it to recalculate its size + * @private + */ + Node.prototype._reset = function() { + this.width = undefined; + this.height = undefined; + }; + /** + * 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; + }; - /************************************ - Week of Year - ************************************/ + /** + * 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); + } - // 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; + switch (this.options.shape) { + case 'circle': + case 'dot': + return this.options.radius+ borderWidth; + case 'ellipse': + var a = this.width / 2; + var b = this.height / 2; + var w = (Math.sin(angle) * a); + var h = (Math.cos(angle) * b); + return a * b / Math.sqrt(w * w + h * h); - if (daysToDayOfWeek > end) { - daysToDayOfWeek -= 7; - } + // TODO: implement distanceToBorder for database + // TODO: implement distanceToBorder for triangle + // TODO: implement distanceToBorder for triangleDown - if (daysToDayOfWeek < end - 7) { - daysToDayOfWeek += 7; - } + 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; + } - adjustedMoment = moment(mom).add(daysToDayOfWeek, 'd'); - return { - week: Math.ceil(adjustedMoment.dayOfYear() / 7), - year: adjustedMoment.year() - }; - } + } + // TODO: implement calculation of distance to border for all shapes + }; - //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; + /** + * 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; + }; - 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; + /** + * 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; + }; - return { - year: dayOfYear > 0 ? year : year - 1, - dayOfYear: dayOfYear > 0 ? dayOfYear : daysInYear(year - 1) + dayOfYear - }; - } + /** + * Store the state before the next step + */ + Node.prototype.storeState = function() { + this.previousState.x = this.x; + this.previousState.y = this.y; + this.previousState.vx = this.vx; + this.previousState.vy = this.vy; + } - /************************************ - Top Level Functions - ************************************/ + /** + * Perform one discrete step for the node + * @param {number} interval Time interval in seconds + */ + Node.prototype.discreteStep = function(interval) { + this.storeState(); + if (!this.xFixed) { + var dx = this.damping * this.vx; // damping force + var ax = (this.fx - dx) / this.options.mass; // acceleration + this.vx += ax * interval; // velocity + this.x += this.vx * interval; // position + } + else { + this.fx = 0; + this.vx = 0; + } - function makeMoment(config) { - var input = config._i, - format = config._f, - res; + if (!this.yFixed) { + var dy = this.damping * this.vy; // damping force + var ay = (this.fy - dy) / this.options.mass; // acceleration + this.vy += ay * interval; // velocity + this.y += this.vy * interval; // position + } + else { + this.fy = 0; + this.vy = 0; + } + }; - config._locale = config._locale || moment.localeData(config._l); - if (input === null || (format === undefined && input === '')) { - return moment.invalid({nullInput: true}); - } - if (typeof input === 'string') { - config._i = input = config._locale.preparse(input); - } + /** + * 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) { + this.storeState(); + if (!this.xFixed) { + var dx = this.damping * this.vx; // damping force + var ax = (this.fx - dx) / this.options.mass; // acceleration + this.vx += ax * interval; // velocity + this.vx = (Math.abs(this.vx) > maxVelocity) ? ((this.vx > 0) ? maxVelocity : -maxVelocity) : this.vx; + this.x += this.vx * interval; // position + } + else { + this.fx = 0; + this.vx = 0; + } - if (moment.isMoment(input)) { - return new Moment(input, true); - } else if (format) { - if (isArray(format)) { - makeDateFromStringAndArray(config); - } else { - makeDateFromStringAndFormat(config); - } - } else { - makeDateFromInput(config); - } + if (!this.yFixed) { + var dy = this.damping * this.vy; // damping force + var ay = (this.fy - dy) / this.options.mass; // acceleration + this.vy += ay * interval; // velocity + this.vy = (Math.abs(this.vy) > maxVelocity) ? ((this.vy > 0) ? maxVelocity : -maxVelocity) : this.vy; + this.y += this.vy * interval; // position + } + else { + this.fy = 0; + this.vy = 0; + } - res = new Moment(config); - if (res._nextDay) { - // Adding is smart enough around DST - res.add(1, 'd'); - res._nextDay = undefined; - } + }; - return res; - } + /** + * 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); + }; - moment = function (input, format, locale, strict) { - var c; + /** + * 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 + */ + Node.prototype.isMoving = function(vmin) { + var velocity = Math.sqrt(Math.pow(this.vx,2) + Math.pow(this.vy,2)); + // this.velocity = Math.sqrt(Math.pow(this.vx,2) + Math.pow(this.vy,2)) + return (velocity > vmin); + }; - if (typeof(locale) === 'boolean') { - strict = locale; - locale = 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 = locale; - c._strict = strict; - c._isUTC = false; - c._pf = defaultParsingFlags(); + /** + * check if this node is selecte + * @return {boolean} selected True if node is selected, else false + */ + Node.prototype.isSelected = function() { + return this.selected; + }; - return makeMoment(c); - }; + /** + * Retrieve the value of the node. Can be undefined + * @return {Number} value + */ + Node.prototype.getValue = function() { + return this.value; + }; - moment.suppressDeprecationWarnings = false; + /** + * 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); + }; - 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 + (config._useUTC ? ' UTC' : '')); - } - ); - // 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; + /** + * 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, total) { + if (!this.radiusFixed && this.value !== undefined) { + var scale = this.options.customScalingFunction(min, max, total, this.value); + var radiusDiff = this.options.radiusMax - this.options.radiusMin; + if (this.options.scaleFontWithValue == true) { + var fontDiff = this.options.fontSizeMax - this.options.fontSizeMin; + this.options.fontSize = this.options.fontSizeMin + scale * fontDiff; } + this.options.radius = this.options.radiusMin + scale * radiusDiff; + } - 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, locale, strict) { - var c; + this.baseRadiusValue = this.options.radius; + }; - if (typeof(locale) === 'boolean') { - strict = locale; - locale = 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 = locale; - c._i = input; - c._f = format; - c._strict = strict; - c._pf = defaultParsingFlags(); + /** + * 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"; + }; - return makeMoment(c).utc(); - }; + /** + * 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"; + }; - // creating with unix timestamp (in seconds) - moment.unix = function (input) { - return moment(input * 1000); - }; + /** + * 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); + }; - // duration - moment.duration = function (input, key) { - var duration = input, - // matching against regexp is expensive, do it on demand - match = null, - sign, - ret, - parseIso, - diffRes; + Node.prototype._resizeImage = function (ctx) { + // TODO: pre calculate the image size - 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]) - }; - } else if (duration == null) {// checks for null or undefined - duration = {}; - } else if (typeof duration === 'object' && - ('from' in duration || 'to' in duration)) { - diffRes = momentsDifference(moment(duration.from), moment(duration.to)); + if (!this.width || !this.height) { // undefined or 0 + var width, height; + if (this.value) { + this.options.radius= this.baseRadiusValue; + var scale = this.imageObj.height / this.imageObj.width; + if (scale !== undefined) { + width = this.options.radius|| this.imageObj.width; + height = this.options.radius* scale || this.imageObj.height; + } + else { + width = 0; + height = 0; + } + } + else { + width = this.imageObj.width; + height = this.imageObj.height; + } + this.width = width; + this.height = height; + } + }; - duration = {}; - duration.ms = diffRes.milliseconds; - duration.M = diffRes.months; - } + Node.prototype._drawImageAtPosition = function (ctx) { + if (this.imageObj.width != 0 ) { + // draw the image + ctx.globalAlpha = 1.0; + ctx.drawImage(this.imageObj, this.left, this.top, this.width, this.height); + } + }; - ret = new Duration(duration); + Node.prototype._drawImageLabel = function (ctx) { + var yLabel; + var offset = 0; + + if (this.height){ + offset = this.height / 2; + var labelDimensions = this.getTextSize(ctx); + + if (labelDimensions.lineCount >= 1){ + offset += labelDimensions.height / 2; + offset += 3; + } + } + + yLabel = this.y + offset; - if (moment.isDuration(input) && hasOwnProp(input, '_locale')) { - ret._locale = input._locale; - } + this._label(ctx, this.label, this.x, yLabel, undefined); + }; - return ret; - }; + Node.prototype._drawImage = function (ctx) { + this._resizeImage(ctx); + this.left = this.x - this.width / 2; + this.top = this.y - this.height / 2; - // version number - moment.version = VERSION; + this._drawImageAtPosition(ctx); - // default format - moment.defaultFormat = isoFormat; + this.boundingBox.top = this.top; + this.boundingBox.left = this.left; + this.boundingBox.right = this.left + this.width; + this.boundingBox.bottom = this.top + this.height; - // constant that refers to the ISO standard - moment.ISO_8601 = function () {}; + this._drawImageLabel(ctx); + this.boundingBox.left = Math.min(this.boundingBox.left, this.labelDimensions.left); + this.boundingBox.right = Math.max(this.boundingBox.right, this.labelDimensions.left + this.labelDimensions.width); + this.boundingBox.bottom = Math.max(this.boundingBox.bottom, this.boundingBox.bottom + this.labelDimensions.height); + }; - // Plugins that add properties should also add the key here (null value), - // so we can properly clone ourselves. - moment.momentProperties = momentProperties; + Node.prototype._resizeCircularImage = function (ctx) { + if(!this.imageObj.src || !this.imageObj.width || !this.imageObj.height){ + if (!this.width) { + var diameter = this.options.radius * 2; + this.width = diameter; + this.height = diameter; + this._swapToImageResizeWhenImageLoaded = true; + } + } + else { + if (this._swapToImageResizeWhenImageLoaded) { + this.width = 0; + this.height = 0; + delete this._swapToImageResizeWhenImageLoaded; + } + this._resizeImage(ctx); + } - // 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; - } - if (limit === undefined) { - return relativeTimeThresholds[threshold]; - } - relativeTimeThresholds[threshold] = limit; - return true; - }; + Node.prototype._drawCircularImage = function (ctx) { + this._resizeCircularImage(ctx); - moment.lang = deprecate( - 'moment.lang is deprecated. Use moment.locale instead.', - function (key, value) { - return moment.locale(key, value); - } - ); + this.left = this.x - this.width / 2; + this.top = this.y - this.height / 2; + + var centerX = this.left + (this.width / 2); + var centerY = this.top + (this.height / 2); + var radius = Math.abs(this.height / 2); - // This function will load locale and then set the global locale. If - // no arguments are passed in, it will simply return the current global - // locale key. - moment.locale = function (key, values) { - var data; - if (key) { - if (typeof(values) !== 'undefined') { - data = moment.defineLocale(key, values); - } - else { - data = moment.localeData(key); - } + this._drawRawCircle(ctx, centerX, centerY, radius); - if (data) { - moment.duration._locale = moment._locale = data; - } - } + ctx.save(); + ctx.circle(this.x, this.y, radius); + ctx.stroke(); + ctx.clip(); - return moment._locale._abbr; - }; + this._drawImageAtPosition(ctx); - moment.defineLocale = function (name, values) { - if (values !== null) { - values.abbr = name; - if (!locales[name]) { - locales[name] = new Locale(); - } - locales[name].set(values); + ctx.restore(); - // backwards compat for now: also set the locale - moment.locale(name); + this.boundingBox.top = this.y - this.options.radius; + this.boundingBox.left = this.x - this.options.radius; + this.boundingBox.right = this.x + this.options.radius; + this.boundingBox.bottom = this.y + this.options.radius; - return locales[name]; - } else { - // useful for testing - delete locales[name]; - return null; - } - }; + this._drawImageLabel(ctx); + + this.boundingBox.left = Math.min(this.boundingBox.left, this.labelDimensions.left); + this.boundingBox.right = Math.max(this.boundingBox.right, this.labelDimensions.left + this.labelDimensions.width); + this.boundingBox.bottom = Math.max(this.boundingBox.bottom, this.boundingBox.bottom + this.labelDimensions.height); + }; - moment.langData = deprecate( - 'moment.langData is deprecated. Use moment.localeData instead.', - function (key) { - return moment.localeData(key); - } - ); + 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; + } + }; - // returns locale data - moment.localeData = function (key) { - var locale; + Node.prototype._drawBox = function (ctx) { + this._resizeBox(ctx); - if (key && key._locale && key._locale._abbr) { - key = key._locale._abbr; - } + this.left = this.x - this.width / 2; + this.top = this.y - this.height / 2; - if (!key) { - return moment._locale; - } + var borderWidth = this.options.borderWidth; + var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; - if (!isArray(key)) { - //short-circuit everything else - locale = loadLocale(key); - if (locale) { - return locale; - } - key = [key]; - } + ctx.strokeStyle = this.selected ? this.options.color.highlight.border : this.hover ? this.options.color.hover.border : this.options.color.border; + ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth); + ctx.lineWidth *= this.networkScaleInv; + ctx.lineWidth = Math.min(this.width,ctx.lineWidth); - return chooseLocale(key); - }; + ctx.fillStyle = this.selected ? this.options.color.highlight.background : this.hover ? this.options.color.hover.background : this.options.color.background; - // compare moment object - moment.isMoment = function (obj) { - return obj instanceof Moment || - (obj != null && hasOwnProp(obj, '_isAMomentObject')); - }; + ctx.roundRect(this.left, this.top, this.width, this.height, this.options.radius); + ctx.fill(); + ctx.stroke(); - // for typechecking Duration objects - moment.isDuration = function (obj) { - return obj instanceof Duration; - }; + this.boundingBox.top = this.top; + this.boundingBox.left = this.left; + this.boundingBox.right = this.left + this.width; + this.boundingBox.bottom = this.top + this.height; - for (i = lists.length - 1; i >= 0; --i) { - makeList(lists[i]); - } + this._label(ctx, this.label, this.x, this.y); + }; - 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; - } + 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; + } + }; - return m; - }; + Node.prototype._drawDatabase = function (ctx) { + this._resizeDatabase(ctx); + this.left = this.x - this.width / 2; + this.top = this.y - this.height / 2; - moment.parseZone = function () { - return moment.apply(null, arguments).parseZone(); - }; + var borderWidth = this.options.borderWidth; + var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; - moment.parseTwoDigitYear = function (input) { - return toInt(input) + (toInt(input) > 68 ? 1900 : 2000); - }; + ctx.strokeStyle = this.selected ? this.options.color.highlight.border : this.hover ? this.options.color.hover.border : this.options.color.border; + ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth); + ctx.lineWidth *= this.networkScaleInv; + ctx.lineWidth = Math.min(this.width,ctx.lineWidth); - moment.isDate = isDate; + ctx.fillStyle = this.selected ? this.options.color.highlight.background : this.hover ? this.options.color.hover.background : this.options.color.background; + ctx.database(this.x - this.width/2, this.y - this.height*0.5, this.width, this.height); + ctx.fill(); + ctx.stroke(); - /************************************ - Moment Prototype - ************************************/ + this.boundingBox.top = this.top; + this.boundingBox.left = this.left; + this.boundingBox.right = this.left + this.width; + this.boundingBox.bottom = this.top + this.height; + this._label(ctx, this.label, this.x, this.y); + }; - extend(moment.fn = Moment.prototype, { - clone : function () { - return moment(this); - }, + Node.prototype._resizeCircle = function (ctx) { + if (!this.width) { + var margin = 5; + var textSize = this.getTextSize(ctx); + var diameter = Math.max(textSize.width, textSize.height) + 2 * margin; + this.options.radius = diameter / 2; - valueOf : function () { - return +this._d - ((this._offset || 0) * 60000); - }, + this.width = diameter; + this.height = diameter; + } + }; - unix : function () { - return Math.floor(+this / 1000); - }, + Node.prototype._drawRawCircle = function (ctx, x, y, radius) { + var borderWidth = this.options.borderWidth; + var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; + + ctx.strokeStyle = this.selected ? this.options.color.highlight.border : this.hover ? this.options.color.hover.border : this.options.color.border; - toString : function () { - return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ'); - }, + ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth); + ctx.lineWidth *= this.networkScaleInv; + ctx.lineWidth = Math.min(this.width,ctx.lineWidth); - toDate : function () { - return this._offset ? new Date(+this) : this._d; - }, + ctx.fillStyle = this.selected ? this.options.color.highlight.background : this.hover ? this.options.color.hover.background : this.options.color.background; + ctx.circle(this.x, this.y, radius); + ctx.fill(); + ctx.stroke(); + }; - toISOString : function () { - var m = moment(this).utc(); - if (0 < m.year() && m.year() <= 9999) { - if ('function' === typeof Date.prototype.toISOString) { - // native implementation is ~50x faster, use it when we can - return this.toDate().toISOString(); - } else { - 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]'); - } - }, + Node.prototype._drawCircle = function (ctx) { + this._resizeCircle(ctx); + this.left = this.x - this.width / 2; + this.top = this.y - this.height / 2; - toArray : function () { - var m = this; - return [ - m.year(), - m.month(), - m.date(), - m.hours(), - m.minutes(), - m.seconds(), - m.milliseconds() - ]; - }, + this._drawRawCircle(ctx, this.x, this.y, this.options.radius); - isValid : function () { - return isValid(this); - }, + this.boundingBox.top = this.y - this.options.radius; + this.boundingBox.left = this.x - this.options.radius; + this.boundingBox.right = this.x + this.options.radius; + this.boundingBox.bottom = this.y + this.options.radius; - isDSTShifted : function () { - if (this._a) { - return this.isValid() && compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()) > 0; - } + this._label(ctx, this.label, this.x, this.y); + }; - return false; - }, + Node.prototype._resizeEllipse = function (ctx) { + if (!this.width) { + var textSize = this.getTextSize(ctx); - parsingFlags : function () { - return extend({}, this._pf); - }, + this.width = textSize.width * 1.5; + this.height = textSize.height * 2; + if (this.width < this.height) { + this.width = this.height; + } + var defaultSize = this.width; + } + }; - invalidAt: function () { - return this._pf.overflow; - }, + Node.prototype._drawEllipse = function (ctx) { + this._resizeEllipse(ctx); + this.left = this.x - this.width / 2; + this.top = this.y - this.height / 2; - utc : function (keepLocalTime) { - return this.utcOffset(0, keepLocalTime); - }, + var borderWidth = this.options.borderWidth; + var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; - local : function (keepLocalTime) { - if (this._isUTC) { - this.utcOffset(0, keepLocalTime); - this._isUTC = false; + ctx.strokeStyle = this.selected ? this.options.color.highlight.border : this.hover ? this.options.color.hover.border : this.options.color.border; - if (keepLocalTime) { - this.subtract(this._dateUtcOffset(), 'm'); - } - } - return this; - }, + ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth); + ctx.lineWidth *= this.networkScaleInv; + ctx.lineWidth = Math.min(this.width,ctx.lineWidth); - format : function (inputString) { - var output = formatMoment(this, inputString || moment.defaultFormat); - return this.localeData().postformat(output); - }, + ctx.fillStyle = this.selected ? this.options.color.highlight.background : this.hover ? this.options.color.hover.background : this.options.color.background; - add : createAdder(1, 'add'), + ctx.ellipse(this.left, this.top, this.width, this.height); + ctx.fill(); + ctx.stroke(); - subtract : createAdder(-1, 'subtract'), + this.boundingBox.top = this.top; + this.boundingBox.left = this.left; + this.boundingBox.right = this.left + this.width; + this.boundingBox.bottom = this.top + this.height; - diff : function (input, units, asFloat) { - var that = makeAs(input, this), - zoneDiff = (that.utcOffset() - this.utcOffset()) * 6e4, - anchor, diff, output, daysAdjust; + this._label(ctx, this.label, this.x, this.y); + }; - units = normalizeUnits(units); + Node.prototype._drawDot = function (ctx) { + this._drawShape(ctx, 'circle'); + }; - if (units === 'year' || units === 'month' || units === 'quarter') { - output = monthDiff(this, that); - if (units === 'quarter') { - output = output / 3; - } else 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); - }, + Node.prototype._drawTriangle = function (ctx) { + this._drawShape(ctx, 'triangle'); + }; - from : function (time, withoutSuffix) { - return moment.duration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix); - }, + Node.prototype._drawTriangleDown = function (ctx) { + this._drawShape(ctx, 'triangleDown'); + }; - fromNow : function (withoutSuffix) { - return this.from(moment(), withoutSuffix); - }, + Node.prototype._drawSquare = function (ctx) { + this._drawShape(ctx, 'square'); + }; - calendar : function (time) { - // We want to compare the start of today, vs this. - // Getting start-of-today depends on whether we're locat/utc/offset - // 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.localeData().calendar(format, this, moment(now))); - }, + Node.prototype._drawStar = function (ctx) { + this._drawShape(ctx, 'star'); + }; - isLeapYear : function () { - return isLeapYear(this.year()); - }, + Node.prototype._resizeShape = function (ctx) { + if (!this.width) { + this.options.radius= this.baseRadiusValue; + var size = 2 * this.options.radius; + this.width = size; + this.height = size; + } + }; - isDST : function () { - return (this.utcOffset() > this.clone().month(0).utcOffset() || - this.utcOffset() > this.clone().month(5).utcOffset()); - }, + Node.prototype._drawShape = function (ctx, shape) { + this._resizeShape(ctx); - day : function (input) { - var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay(); - if (input != null) { - input = parseWeekday(input, this.localeData()); - return this.add(input - day, 'd'); - } else { - return day; - } - }, + this.left = this.x - this.width / 2; + this.top = this.y - this.height / 2; + + var borderWidth = this.options.borderWidth; + var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; + var radiusMultiplier = 2; + + // 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; + } - month : makeAccessor('Month', true), + ctx.strokeStyle = this.selected ? this.options.color.highlight.border : this.hover ? this.options.color.hover.border : this.options.color.border; + ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth); + ctx.lineWidth *= this.networkScaleInv; + ctx.lineWidth = Math.min(this.width,ctx.lineWidth); - 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 */ - } + ctx.fillStyle = this.selected ? this.options.color.highlight.background : this.hover ? this.options.color.hover.background : this.options.color.background; + ctx[shape](this.x, this.y, this.options.radius); + ctx.fill(); + ctx.stroke(); - // weeks are a special case - if (units === 'week') { - this.weekday(0); - } else if (units === 'isoWeek') { - this.isoWeekday(1); - } + this.boundingBox.top = this.y - this.options.radius; + this.boundingBox.left = this.x - this.options.radius; + this.boundingBox.right = this.x + this.options.radius; + this.boundingBox.bottom = this.y + this.options.radius; - // quarters are also special - if (units === 'quarter') { - this.month(Math.floor(this.month() / 3) * 3); - } + if (this.label) { + this._label(ctx, this.label, this.x, this.y + this.height / 2, undefined, 'hanging',true); + this.boundingBox.left = Math.min(this.boundingBox.left, this.labelDimensions.left); + this.boundingBox.right = Math.max(this.boundingBox.right, this.labelDimensions.left + this.labelDimensions.width); + this.boundingBox.bottom = Math.max(this.boundingBox.bottom, this.boundingBox.bottom + this.labelDimensions.height); + } + }; - return this; - }, + 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; + } + }; - endOf: function (units) { - units = normalizeUnits(units); - if (units === undefined || units === 'millisecond') { - return this; - } - return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms'); - }, + Node.prototype._drawText = function (ctx) { + this._resizeText(ctx); + this.left = this.x - this.width / 2; + this.top = this.y - this.height / 2; - isAfter: function (input, units) { - var inputMs; - units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond'); - if (units === 'millisecond') { - input = moment.isMoment(input) ? input : moment(input); - return +this > +input; - } else { - inputMs = moment.isMoment(input) ? +input : +moment(input); - return inputMs < +this.clone().startOf(units); - } - }, + this._label(ctx, this.label, this.x, this.y); - isBefore: function (input, units) { - var inputMs; - units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond'); - if (units === 'millisecond') { - input = moment.isMoment(input) ? input : moment(input); - return +this < +input; - } else { - inputMs = moment.isMoment(input) ? +input : +moment(input); - return +this.clone().endOf(units) < inputMs; - } - }, + this.boundingBox.top = this.top; + this.boundingBox.left = this.left; + this.boundingBox.right = this.left + this.width; + this.boundingBox.bottom = this.top + this.height; + }; - isBetween: function (from, to, units) { - return this.isAfter(from, units) && this.isBefore(to, units); - }, + Node.prototype._resizeIcon = function (ctx) { + if (!this.width) { + var margin = 5; + var iconSize = + { + width: Number(this.options.iconSize), + height: Number(this.options.iconSize) + }; + this.width = iconSize.width + 2 * margin; + this.height = iconSize.height + 2 * margin; + } + }; - isSame: function (input, units) { - var inputMs; - units = normalizeUnits(units || 'millisecond'); - if (units === 'millisecond') { - input = moment.isMoment(input) ? input : moment(input); - return +this === +input; - } else { - inputMs = +moment(input); - return +(this.clone().startOf(units)) <= inputMs && inputMs <= +(this.clone().endOf(units)); - } - }, + Node.prototype._drawIcon = function (ctx) { + this._resizeIcon(ctx); - 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; - } - ), + this.options.iconSize = this.options.iconSize || 50; - 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; - } - ), + this.left = this.x - this.width / 2; + this.top = this.y - this.height / 2; + this._icon(ctx); - zone : deprecate( - 'moment().zone is deprecated, use moment().utcOffset instead. ' + - 'https://github.com/moment/moment/issues/1779', - function (input, keepLocalTime) { - if (input != null) { - if (typeof input !== 'string') { - input = -input; - } - this.utcOffset(input, keepLocalTime); + this.boundingBox.top = this.y - this.options.iconSize/2; + this.boundingBox.left = this.x - this.options.iconSize/2; + this.boundingBox.right = this.x + this.options.iconSize/2; + this.boundingBox.bottom = this.y + this.options.iconSize/2; - return this; - } else { - return -this.utcOffset(); - } - } - ), + if (this.label) { + var iconTextSpacing = 5; + this._label(ctx, this.label, this.x, this.y + this.height / 2 + iconTextSpacing, 'top', true); - // keepLocalTime = true means only change the timezone, without - // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]--> - // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset - // +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. - utcOffset : function (input, keepLocalTime) { - var offset = this._offset || 0, - localAdjust; - if (input != null) { - if (typeof input === 'string') { - input = utcOffsetFromString(input); - } - if (Math.abs(input) < 16) { - input = input * 60; - } - if (!this._isUTC && keepLocalTime) { - localAdjust = this._dateUtcOffset(); - } - this._offset = input; - this._isUTC = true; - if (localAdjust != null) { - this.add(localAdjust, 'm'); - } - if (offset !== input) { - if (!keepLocalTime || this._changeInProgress) { - addOrSubtractDurationFromMoment(this, - moment.duration(input - offset, 'm'), 1, false); - } else if (!this._changeInProgress) { - this._changeInProgress = true; - moment.updateOffset(this, true); - this._changeInProgress = null; - } - } + this.boundingBox.left = Math.min(this.boundingBox.left, this.labelDimensions.left); + this.boundingBox.right = Math.max(this.boundingBox.right, this.labelDimensions.left + this.labelDimensions.width); + this.boundingBox.bottom = Math.max(this.boundingBox.bottom, this.boundingBox.bottom + this.labelDimensions.height); + } + }; - return this; - } else { - return this._isUTC ? offset : this._dateUtcOffset(); - } - }, + Node.prototype._icon = function (ctx) { + var relativeIconSize = Number(this.options.iconSize) * this.networkScale; + + if (this.options.icon && relativeIconSize > this.options.fontDrawThreshold - 1) { - isLocal : function () { - return !this._isUTC; - }, + var iconSize = Number(this.options.iconSize); - isUtcOffset : function () { - return this._isUTC; - }, + ctx.font = (this.selected ? "bold " : "") + iconSize + "px " + this.options.iconFontFace; - isUtc : function () { - return this._isUTC && this._offset === 0; - }, + // draw icon + ctx.fillStyle = this.options.iconColor || "black"; + ctx.textAlign = "center"; + ctx.textBaseline = "middle"; + ctx.fillText(this.options.icon, this.x, this.y); + } + }; + + Node.prototype._label = function (ctx, text, x, y, align, baseline, labelUnderNode) { + var relativeFontSize = Number(this.options.fontSize) * this.networkScale; + if (text && relativeFontSize >= this.options.fontDrawThreshold - 1) { + var fontSize = Number(this.options.fontSize); - zoneAbbr : function () { - return this._isUTC ? 'UTC' : ''; - }, + // this ensures that there will not be HUGE letters on screen by setting an upper limit on the visible text size (regardless of zoomLevel) + if (relativeFontSize >= this.options.fontSizeMaxVisible) { + fontSize = Number(this.options.fontSizeMaxVisible) * this.networkScaleInv; + } - zoneName : function () { - return this._isUTC ? 'Coordinated Universal Time' : ''; - }, + // fade in when relative scale is between threshold and threshold - 1 + var fontColor = this.options.fontColor || "#000000"; + var strokecolor = this.options.fontStrokeColor; + if (relativeFontSize <= this.options.fontDrawThreshold) { + var opacity = Math.max(0,Math.min(1,1 - (this.options.fontDrawThreshold - relativeFontSize))); + fontColor = util.overrideOpacity(fontColor, opacity); + strokecolor = util.overrideOpacity(strokecolor, opacity); - parseZone : function () { - if (this._tzm) { - this.utcOffset(this._tzm); - } else if (typeof this._i === 'string') { - this.utcOffset(utcOffsetFromString(this._i)); - } - return this; - }, + } - hasAlignedHourOffset : function (input) { - if (!input) { - input = 0; - } - else { - input = moment(input).utcOffset(); - } + ctx.font = (this.selected ? "bold " : "") + fontSize + "px " + this.options.fontFace; - return (this.utcOffset() - input) % 60 === 0; - }, + var lines = text.split('\n'); + var lineCount = lines.length; + var yLine = y + (1 - lineCount) / 2 * fontSize; + if (labelUnderNode == true) { + yLine = y + (1 - lineCount) / (2 * fontSize); + } - daysInMonth : function () { - return daysInMonth(this.year(), this.month()); - }, + // font fill from edges now for nodes! + var width = ctx.measureText(lines[0]).width; + for (var i = 1; i < lineCount; i++) { + var lineWidth = ctx.measureText(lines[i]).width; + width = lineWidth > width ? lineWidth : width; + } + var height = fontSize * lineCount; + var left = x - width / 2; + var top = y - height / 2; + if (baseline == "hanging") { + top += 0.5 * fontSize; + top += 4; // distance from node, required because we use hanging. Hanging has less difference between browsers + yLine += 4; // distance from node + } + this.labelDimensions = {top:top,left:left,width:width,height:height,yLine:yLine}; - dayOfYear : function (input) { - var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1; - return input == null ? dayOfYear : this.add((input - dayOfYear), 'd'); - }, + // create the fontfill background + if (this.options.fontFill !== undefined && this.options.fontFill !== null && this.options.fontFill !== "none") { + ctx.fillStyle = this.options.fontFill; + ctx.fillRect(left, top, width, height); + } - quarter : function (input) { - return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3); - }, + // draw text + ctx.fillStyle = fontColor; + ctx.textAlign = align || "center"; + ctx.textBaseline = baseline || "middle"; + if (this.options.fontStrokeWidth > 0){ + ctx.lineWidth = this.options.fontStrokeWidth; + ctx.strokeStyle = strokecolor; + ctx.lineJoin = 'round'; + } + for (var i = 0; i < lineCount; i++) { + if(this.options.fontStrokeWidth){ + ctx.strokeText(lines[i], x, yLine); + } + ctx.fillText(lines[i], x, yLine); + yLine += fontSize; + } + } + }; - weekYear : function (input) { - var year = weekOfYear(this, this.localeData()._week.dow, this.localeData()._week.doy).year; - return input == null ? year : this.add((input - year), 'y'); - }, - isoWeekYear : function (input) { - var year = weekOfYear(this, 1, 4).year; - return input == null ? year : this.add((input - year), 'y'); - }, + Node.prototype.getTextSize = function(ctx) { + if (this.label !== undefined) { + var fontSize = Number(this.options.fontSize); + if (fontSize * this.networkScale > this.options.fontSizeMaxVisible) { + fontSize = Number(this.options.fontSizeMaxVisible) * this.networkScaleInv; + } + ctx.font = (this.selected ? "bold " : "") + fontSize + "px " + this.options.fontFace; - week : function (input) { - var week = this.localeData().week(this); - return input == null ? week : this.add((input - week) * 7, 'd'); - }, + var lines = this.label.split('\n'), + height = (fontSize + 4) * lines.length, + width = 0; - isoWeek : function (input) { - var week = weekOfYear(this, 1, 4).week; - return input == null ? week : this.add((input - week) * 7, 'd'); - }, + for (var i = 0, iMax = lines.length; i < iMax; i++) { + width = Math.max(width, ctx.measureText(lines[i]).width); + } - weekday : function (input) { - var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7; - return input == null ? weekday : this.add(input - weekday, 'd'); - }, + return {"width": width, "height": height, lineCount: lines.length}; + } + else { + return {"width": 0, "height": 0, lineCount: 0}; + } + }; - 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); - }, + /** + * 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; + } + }; - isoWeeksInYear : function () { - return weeksInYear(this.year(), 1, 4); - }, + /** + * 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); + }; - weeksInYear : function () { - var weekInfo = this.localeData()._week; - return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy); - }, + /** + * 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; + }; - get : function (units) { - units = normalizeUnits(units); - return this[units](); - }, - set : function (units, value) { - var unit; - if (typeof units === 'object') { - for (unit in units) { - this.set(unit, units[unit]); - } - } - else { - units = normalizeUnits(units); - if (typeof this[units] === 'function') { - this[units](value); - } - } - return this; - }, + /** + * 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; + }; - // If passed a locale key, it will set the locale for this - // instance. Otherwise, it will return the locale configuration - // variables for this instance. - locale : function (key) { - var newLocaleData; - if (key === undefined) { - return this._locale._abbr; - } else { - newLocaleData = moment.localeData(key); - if (newLocaleData != null) { - this._locale = newLocaleData; - } - return this; - } - }, - lang : deprecate( - 'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.', - function (key) { - if (key === undefined) { - return this.localeData(); - } else { - return this.locale(key); - } - } - ), + /** + * 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; + }; - localeData : function () { - return this._locale; - }, - _dateUtcOffset : function () { - // On Firefox.24 Date#getTimezoneOffset returns a floating point. - // https://github.com/moment/moment/pull/1871 - return -Math.round(this._d.getTimezoneOffset() / 15) * 15; - } + /** + * 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.options.mass) : Math.sqrt(energyBefore/this.options.mass); + this.vx = Math.sqrt(energyBefore/this.options.mass); + energyBefore = this.vy * this.vy * massBeforeClustering; + //this.vy = (this.vy < 0) ? -Math.sqrt(energyBefore/this.options.mass) : Math.sqrt(energyBefore/this.options.mass); + this.vy = Math.sqrt(energyBefore/this.options.mass); + }; - }); + module.exports = Node; - function rawMonthSetter(mom, value) { - var dayOfMonth; - // TODO: Move this out of here! - if (typeof value === 'string') { - value = mom.localeData().monthsParse(value); - // TODO: Another silent failure? - if (typeof value !== 'number') { - return mom; - } - } +/***/ }, +/* 57 */ +/***/ function(module, exports, __webpack_require__) { - dayOfMonth = Math.min(mom.date(), - daysInMonth(mom.year(), value)); - mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth); - return mom; - } + var util = __webpack_require__(1); + var Node = __webpack_require__(56); - function rawGetter(mom, unit) { - return mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit](); - } + /** + * @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, networkConstants) { + if (!network) { + throw "No network provided"; + } + var fields = ['edges','physics']; + var constants = util.selectiveBridgeObject(fields,networkConstants); + this.options = constants.edges; - function rawSetter(mom, unit, value) { - if (unit === 'Month') { - return rawMonthSetter(mom, value); - } else { - return mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value); - } - } + this.physics = constants.physics; + this.options['smoothCurves'] = networkConstants['smoothCurves']; - 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)); + this.network = network; - // 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; + // initialize variables + this.id = undefined; + this.fromId = undefined; + this.toId = undefined; + this.title = undefined; + this.widthSelected = this.options.width * this.options.widthSelectionMultiplier; + this.value = undefined; + this.selected = false; + this.hover = false; + this.labelDimensions = {top:0,left:0,width:0,height:0,yLine:0}; // could be cached + this.dirtyLabel = true; + this.colorDirty = true; - // add aliased format methods - moment.fn.toJSON = moment.fn.toISOString; + this.from = null; // a node + this.to = null; // a node + this.via = null; // a temp node - // alias isUtc for dev-friendliness - moment.fn.isUTC = moment.fn.isUtc; + this.fromBackup = null; // used to clean up after reconnect (used for manipulation) + this.toBackup = null; // used to clean up after reconnect (used for manipulation) - /************************************ - Duration Prototype - ************************************/ + // 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.fromArray = []; + this.toArray = []; + this.connected = false; - function daysToYears (days) { - // 400 years have 146097 days (taking into account leap year rules) - return days * 400 / 146097; - } + this.widthFixed = false; + this.lengthFixed = false; - function yearsToDays (years) { - // years * 365 + absRound(years / 4) - - // absRound(years / 100) + absRound(years / 400); - return years * 146097 / 400; - } + this.setProperties(properties); - extend(moment.duration.fn = Duration.prototype, { + this.controlNodesEnabled = false; + this.controlNodes = {from:null, to:null, positions:{}}; + this.connectedNode = null; + } - _bubble : function () { - var milliseconds = this._milliseconds, - days = this._days, - months = this._months, - data = this._data, - seconds, minutes, hours, years = 0; + /** + * 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) { + this.colorDirty = true; + if (!properties) { + return; + } + this.properties = properties; - // The following code bubbles up values, see the tests for - // examples of what that means. - data.milliseconds = milliseconds % 1000; + var fields = ['style','fontSize','fontFace','fontColor','fontFill','fontStrokeWidth','fontStrokeColor','width', + 'widthSelectionMultiplier','hoverWidth','arrowScaleFactor','dash','inheritColor','labelAlignment', 'opacity', + 'customScalingFunction','useGradients','value' + ]; + util.selectiveDeepExtend(fields, this.options, properties); - seconds = absRound(milliseconds / 1000); - data.seconds = seconds % 60; + if (properties.from !== undefined) {this.fromId = properties.from;} + if (properties.to !== undefined) {this.toId = properties.to;} - minutes = absRound(seconds / 60); - data.minutes = minutes % 60; + if (properties.id !== undefined) {this.id = properties.id;} + if (properties.label !== undefined) {this.label = properties.label; this.dirtyLabel = true;} - hours = absRound(minutes / 60); - data.hours = hours % 24; + if (properties.title !== undefined) {this.title = properties.title;} + if (properties.value !== undefined) {this.value = properties.value;} + if (properties.length !== undefined) {this.physics.springLength = properties.length;} - days += absRound(hours / 24); + if (properties.color !== undefined) { + this.options.inheritColor = false; + if (util.isString(properties.color)) { + this.options.color.color = properties.color; + this.options.color.highlight = properties.color; + } + else { + if (properties.color.color !== undefined) {this.options.color.color = properties.color.color;} + if (properties.color.highlight !== undefined) {this.options.color.highlight = properties.color.highlight;} + if (properties.color.hover !== undefined) {this.options.color.hover = properties.color.hover;} + } + } - // Accurately convert days to years, assume start from year 0. - years = absRound(daysToYears(days)); - days -= absRound(yearsToDays(years)); - // 30 days to a month - // TODO (iskren): Use anchor date (like 1st Jan) to compute this. - months += absRound(days / 30); - days %= 30; - // 12 months -> 1 year - years += absRound(months / 12); - months %= 12; + // A node is connected when it has a from and to node. + this.connect(); - data.days = days; - data.months = months; - data.years = years; - }, + this.widthFixed = this.widthFixed || (properties.width !== undefined); + this.lengthFixed = this.lengthFixed || (properties.length !== undefined); - abs : function () { - this._milliseconds = Math.abs(this._milliseconds); - this._days = Math.abs(this._days); - this._months = Math.abs(this._months); + this.widthSelected = this.options.width* this.options.widthSelectionMultiplier; - this._data.milliseconds = Math.abs(this._data.milliseconds); - this._data.seconds = Math.abs(this._data.seconds); - this._data.minutes = Math.abs(this._data.minutes); - this._data.hours = Math.abs(this._data.hours); - this._data.months = Math.abs(this._data.months); - this._data.years = Math.abs(this._data.years); + // set draw method based on style + switch (this.options.style) { + case 'line': this.draw = this._drawLine; break; + case 'arrow': this.draw = this._drawArrow; break; + case 'arrow-center': this.draw = this._drawArrowCenter; break; + case 'dash-line': this.draw = this._drawDashLine; break; + default: this.draw = this._drawLine; break; + } + }; - return this; - }, - weeks : function () { - return absRound(this.days() / 7); - }, + /** + * Connect an edge to its nodes + */ + Edge.prototype.connect = function () { + this.disconnect(); - valueOf : function () { - return this._milliseconds + - this._days * 864e5 + - (this._months % 12) * 2592e6 + - toInt(this._months / 12) * 31536e6; - }, + this.from = this.network.nodes[this.fromId] || null; + this.to = this.network.nodes[this.toId] || null; + this.connected = (this.from !== null && this.to !== null); - humanize : function (withSuffix) { - var output = relativeTime(this, !withSuffix, this.localeData()); + if (this.connected === true) { + this.from.attachEdge(this); + this.to.attachEdge(this); + } + else { + if (this.from) { + this.from.detachEdge(this); + } + if (this.to) { + this.to.detachEdge(this); + } + } + }; - if (withSuffix) { - output = this.localeData().pastFuture(+this, output); - } + /** + * 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; + } - return this.localeData().postformat(output); - }, + this.connected = false; + }; - add : function (input, val) { - // supports only 2.0-style add(1, 's') or add(moment) - var dur = moment.duration(input, val); + /** + * 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; + }; - this._milliseconds += dur._milliseconds; - this._days += dur._days; - this._months += dur._months; - this._bubble(); + /** + * Retrieve the value of the edge. Can be undefined + * @return {Number} value + */ + Edge.prototype.getValue = function() { + return this.value; + }; - return this; - }, + /** + * 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, total) { + if (!this.widthFixed && this.value !== undefined) { + var scale = this.options.customScalingFunction(min, max, total, this.value); + var widthDiff = this.options.widthMax - this.options.widthMin; + this.options.width = this.options.widthMin + scale * widthDiff; + this.widthSelected = this.options.width* this.options.widthSelectionMultiplier; + } + }; - subtract : function (input, val) { - var dur = moment.duration(input, val); + /** + * 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"; + }; - this._milliseconds -= dur._milliseconds; - this._days -= dur._days; - this._months -= dur._months; + /** + * Check if this object is overlapping with the provided object + * @param {Object} obj an object with parameters left, top + * @return {boolean} True if location is located on the edge + */ + Edge.prototype.isOverlappingWith = function(obj) { + if (this.connected) { + var distMax = 10; + var xFrom = this.from.x; + var yFrom = this.from.y; + var xTo = this.to.x; + var yTo = this.to.y; + var xObj = obj.left; + var yObj = obj.top; - this._bubble(); + var dist = this._getDistanceToEdge(xFrom, yFrom, xTo, yTo, xObj, yObj); - return this; - }, + return (dist < distMax); + } + else { + return false + } + }; - get : function (units) { - units = normalizeUnits(units); - return this[units.toLowerCase() + 's'](); - }, + Edge.prototype._getColor = function(ctx) { + var colorObj = this.options.color; + if (this.options.useGradients == true) { + var grd = ctx.createLinearGradient(this.from.x, this.from.y, this.to.x, this.to.y); + var fromColor, toColor; + fromColor = this.from.options.color.highlight.border; + toColor = this.to.options.color.highlight.border; - as : function (units) { - var days, months; - units = normalizeUnits(units); - if (units === 'month' || units === 'year') { - days = this._days + this._milliseconds / 864e5; - months = this._months + daysToYears(days) * 12; - return units === 'month' ? months : months / 12; - } else { - // handle milliseconds separately because of floating point math errors (issue #1867) - days = this._days + Math.round(yearsToDays(this._months / 12)); - switch (units) { - case 'week': return days / 7 + this._milliseconds / 6048e5; - case 'day': return days + this._milliseconds / 864e5; - case 'hour': return days * 24 + this._milliseconds / 36e5; - case 'minute': return days * 24 * 60 + this._milliseconds / 6e4; - case 'second': return days * 24 * 60 * 60 + this._milliseconds / 1000; - // Math.floor prevents floating point math errors here - case 'millisecond': return Math.floor(days * 24 * 60 * 60 * 1000) + this._milliseconds; - default: throw new Error('Unknown unit ' + units); - } - } - }, + if (this.from.selected == false && this.to.selected == false) { + fromColor = util.overrideOpacity(this.from.options.color.border, this.options.opacity); + toColor = util.overrideOpacity(this.to.options.color.border, this.options.opacity); + } + else if (this.from.selected == true && this.to.selected == false) { + toColor = this.to.options.color.border; + } + else if (this.from.selected == false && this.to.selected == true) { + fromColor = this.from.options.color.border; + } + grd.addColorStop(0, fromColor); + grd.addColorStop(1, toColor); + return grd; + } - lang : moment.fn.lang, - locale : moment.fn.locale, + if (this.colorDirty === true) { - toIsoString : deprecate( - 'toIsoString() is deprecated. Please use toISOString() instead ' + - '(notice the capitals)', - function () { - return this.toISOString(); - } - ), + if (this.options.inheritColor == "to") { + colorObj = { + highlight: this.to.options.color.highlight.border, + hover: this.to.options.color.hover.border, + color: util.overrideOpacity(this.from.options.color.border, this.options.opacity) + }; + } + else if (this.options.inheritColor == "from" || this.options.inheritColor == true) { + colorObj = { + highlight: this.from.options.color.highlight.border, + hover: this.from.options.color.hover.border, + color: util.overrideOpacity(this.from.options.color.border, this.options.opacity) + }; + } + this.options.color = colorObj; + this.colorDirty = false; + } - 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' : ''); - }, + if (this.selected == true) {return colorObj.highlight;} + else if (this.hover == true) {return colorObj.hover;} + else {return colorObj.color;} + }; - localeData : function () { - return this._locale; - }, - toJSON : function () { - return this.toISOString(); - } - }); + /** + * 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); + ctx.lineWidth = this._getLineWidth(); - moment.duration.fn.toString = moment.duration.fn.toISOString; + if (this.from != this.to) { + // draw line + var via = this._line(ctx); - function makeDurationGetter(name) { - moment.duration.fn[name] = function () { - return this._data[name]; - }; + // draw label + var point; + if (this.label) { + if (this.options.smoothCurves.enabled == true && via != null) { + var midpointX = 0.5*(0.5*(this.from.x + via.x) + 0.5*(this.to.x + via.x)); + var midpointY = 0.5*(0.5*(this.from.y + via.y) + 0.5*(this.to.y + via.y)); + point = {x:midpointX, y:midpointY}; + } + else { + point = this._pointOnLine(0.5); + } + this._label(ctx, this.label, point.x, point.y); + } + } + else { + var x, y; + var radius = this.physics.springLength / 4; + var node = this.from; + if (!node.width) { + node.resize(ctx); + } + if (node.width > node.height) { + x = node.x + node.width / 2; + y = node.y - radius; + } + else { + x = node.x + radius; + y = node.y - node.height / 2; + } + this._circle(ctx, x, y, radius); + point = this._pointOnCircle(x, y, radius, 0.5); + this._label(ctx, this.label, point.x, point.y); + } + }; + + /** + * 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.max(Math.min(this.widthSelected, this.options.widthMax), 0.3*this.networkScaleInv); + } + else { + if (this.hover == true) { + return Math.max(Math.min(this.options.hoverWidth, this.options.widthMax), 0.3*this.networkScaleInv); + } + else { + return Math.max(this.options.width, 0.3*this.networkScaleInv); } + } + }; - for (i in unitMillisecondFactors) { - if (hasOwnProp(unitMillisecondFactors, i)) { - makeDurationGetter(i.toLowerCase()); + Edge.prototype._getViaCoordinates = function () { + if (this.options.smoothCurves.dynamic == true && this.options.smoothCurves.enabled == true ) { + return this.via; + } + else if (this.options.smoothCurves.enabled == false) { + return {x:0,y:0}; + } + else { + var xVia = null; + var yVia = null; + var factor = this.options.smoothCurves.roundness; + var type = this.options.smoothCurves.type; + var dx = Math.abs(this.from.x - this.to.x); + var dy = Math.abs(this.from.y - this.to.y); + if (type == 'discrete' || type == 'diagonalCross') { + if (Math.abs(this.from.x - this.to.x) < Math.abs(this.from.y - this.to.y)) { + if (this.from.y > this.to.y) { + if (this.from.x < this.to.x) { + xVia = this.from.x + factor * dy; + yVia = this.from.y - factor * dy; + } + else if (this.from.x > this.to.x) { + xVia = this.from.x - factor * dy; + yVia = this.from.y - factor * dy; + } + } + else if (this.from.y < this.to.y) { + if (this.from.x < this.to.x) { + xVia = this.from.x + factor * dy; + yVia = this.from.y + factor * dy; + } + else if (this.from.x > this.to.x) { + xVia = this.from.x - factor * dy; + yVia = this.from.y + factor * dy; + } + } + if (type == "discrete") { + xVia = dx < factor * dy ? this.from.x : xVia; + } + } + else if (Math.abs(this.from.x - this.to.x) > Math.abs(this.from.y - this.to.y)) { + if (this.from.y > this.to.y) { + if (this.from.x < this.to.x) { + xVia = this.from.x + factor * dx; + yVia = this.from.y - factor * dx; + } + else if (this.from.x > this.to.x) { + xVia = this.from.x - factor * dx; + yVia = this.from.y - factor * dx; + } + } + else if (this.from.y < this.to.y) { + if (this.from.x < this.to.x) { + xVia = this.from.x + factor * dx; + yVia = this.from.y + factor * dx; + } + else if (this.from.x > this.to.x) { + xVia = this.from.x - factor * dx; + yVia = this.from.y + factor * dx; + } + } + if (type == "discrete") { + yVia = dy < factor * dx ? this.from.y : yVia; } + } } - - moment.duration.fn.asMilliseconds = function () { - return this.as('ms'); - }; - moment.duration.fn.asSeconds = function () { - return this.as('s'); - }; - moment.duration.fn.asMinutes = function () { - return this.as('m'); - }; - moment.duration.fn.asHours = function () { - return this.as('h'); - }; - moment.duration.fn.asDays = function () { - return this.as('d'); - }; - moment.duration.fn.asWeeks = function () { - return this.as('weeks'); - }; - moment.duration.fn.asMonths = function () { - return this.as('M'); - }; - moment.duration.fn.asYears = function () { - return this.as('y'); - }; - - /************************************ - Default Locale - ************************************/ - - - // Set default locale, other locale will inherit from English. - moment.locale('en', { - ordinalParse: /\d{1,2}(th|st|nd|rd)/, - 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; + 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; } - }); - - /* EMBED_LOCALES */ - - /************************************ - Exposing Moment - ************************************/ - - function makeGlobal(shouldDeprecate) { - /*global ender:false */ - if (typeof ender !== 'undefined') { - return; + else { + yVia = this.to.y + (1 - factor) * dy; } - 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; + } + else if (Math.abs(this.from.x - this.to.x) > Math.abs(this.from.y - this.to.y)) { // left - right + if (this.from.x < this.to.x) { + xVia = this.to.x - (1 - factor) * dx; } + else { + xVia = this.to.x + (1 - factor) * dx; + } + yVia = this.from.y; + } + } + else if (type == 'horizontal') { + if (this.from.x < this.to.x) { + xVia = this.to.x - (1 - factor) * dx; + } + else { + xVia = this.to.x + (1 - factor) * dx; + } + yVia = this.from.y; + } + else if (type == 'vertical') { + xVia = this.from.x; + if (this.from.y < this.to.y) { + yVia = this.to.y - (1 - factor) * dy; + } + else { + yVia = this.to.y + (1 - factor) * dy; + } } + else if (type == 'curvedCW') { + var dx = this.to.x - this.from.x; + var dy = this.from.y - this.to.y; + var radius = Math.sqrt(dx*dx + dy*dy); + var pi = Math.PI; - // 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; - } + var originalAngle = Math.atan2(dy,dx); + var myAngle = (originalAngle + ((factor * 0.5) + 0.5) * pi) % (2 * pi); - return moment; - }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); - makeGlobal(true); - } else { - makeGlobal(); + xVia = this.from.x + (factor*0.5 + 0.5)*radius*Math.sin(myAngle); + yVia = this.from.y + (factor*0.5 + 0.5)*radius*Math.cos(myAngle); } - }).call(this); - - /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()), __webpack_require__(71)(module))) - -/***/ }, -/* 60 */ -/***/ function(module, exports, __webpack_require__) { + else if (type == 'curvedCCW') { + var dx = this.to.x - this.from.x; + var dy = this.from.y - this.to.y; + var radius = Math.sqrt(dx*dx + dy*dy); + var pi = Math.PI; - /** - * Creation of the ClusterMixin var. - * - * This contains all the functions the Network object can use to employ clustering - */ + var originalAngle = Math.atan2(dy,dx); + var myAngle = (originalAngle + ((-factor * 0.5) + 0.5) * pi) % (2 * pi); - /** - * 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); + xVia = this.from.x + (factor*0.5 + 0.5)*radius*Math.sin(myAngle); + yVia = this.from.y + (factor*0.5 + 0.5)*radius*Math.cos(myAngle); + } + else { // continuous + if (Math.abs(this.from.x - this.to.x) < Math.abs(this.from.y - this.to.y)) { + if (this.from.y > this.to.y) { + if (this.from.x < this.to.x) { + xVia = this.from.x + factor * dy; + yVia = this.from.y - factor * dy; + xVia = this.to.x < xVia ? this.to.x : xVia; + } + else if (this.from.x > this.to.x) { + xVia = this.from.x - factor * dy; + yVia = this.from.y - factor * dy; + xVia = this.to.x > xVia ? this.to.x : xVia; + } + } + else if (this.from.y < this.to.y) { + if (this.from.x < this.to.x) { + xVia = this.from.x + factor * dy; + yVia = this.from.y + factor * dy; + xVia = this.to.x < xVia ? this.to.x : xVia; + } + else if (this.from.x > this.to.x) { + xVia = this.from.x - factor * dy; + yVia = this.from.y + factor * dy; + xVia = this.to.x > xVia ? this.to.x : xVia; + } + } + } + else if (Math.abs(this.from.x - this.to.x) > Math.abs(this.from.y - this.to.y)) { + if (this.from.y > this.to.y) { + if (this.from.x < this.to.x) { + xVia = this.from.x + factor * dx; + yVia = this.from.y - factor * dx; + yVia = this.to.y > yVia ? this.to.y : yVia; + } + else if (this.from.x > this.to.x) { + xVia = this.from.x - factor * dx; + yVia = this.from.y - factor * dx; + yVia = this.to.y > yVia ? this.to.y : yVia; + } + } + else if (this.from.y < this.to.y) { + if (this.from.x < this.to.x) { + xVia = this.from.x + factor * dx; + yVia = this.from.y + factor * dx; + yVia = this.to.y < yVia ? this.to.y : yVia; + } + else if (this.from.x > this.to.x) { + xVia = this.from.x - factor * dx; + yVia = this.from.y + factor * dx; + yVia = this.to.y < yVia ? this.to.y : yVia; + } + } + } + } - // 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.constants.stabilize == true) { - this._stabilize(); - } - this.start(); + return {x: xVia, y: yVia}; + } }; /** - * This function clusters until the initialMaxNodes has been reached - * - * @param {Number} maxNumberOfNodes - * @param {Boolean} reposition + * Draw a line between two nodes + * @param {CanvasRenderingContext2D} ctx + * @private */ - exports.clusterToFit = function(maxNumberOfNodes, reposition) { - var numberOfNodes = this.nodeIndices.length; - - 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.0) { - this.forceAggregateHubs(true); - this.normalizeClusterLevels(); + Edge.prototype._line = function (ctx) { + // draw a straight line + ctx.beginPath(); + ctx.moveTo(this.from.x, this.from.y); + if (this.options.smoothCurves.enabled == true) { + if (this.options.smoothCurves.dynamic == false) { + var via = this._getViaCoordinates(); + if (via.x == null) { + ctx.lineTo(this.to.x, this.to.y); + ctx.stroke(); + return null; + } + else { + // this.via.x = via.x; + // this.via.y = via.y; + ctx.quadraticCurveTo(via.x,via.y,this.to.x, this.to.y); + ctx.stroke(); + //ctx.circle(via.x,via.y,2) + //ctx.stroke(); + return via; + } } else { - this.increaseClusterLevel(); // this also includes a cluster normalization + ctx.quadraticCurveTo(this.via.x,this.via.y,this.to.x, this.to.y); + ctx.stroke(); + return this.via; } - this.forceAggregateHubs(true); - 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(); + else { + ctx.lineTo(this.to.x, this.to.y); + ctx.stroke(); + return null; } - this._updateCalculationNodes(); }; /** - * This function can be called to open up a specific cluster. - * It will unpack the cluster back one level. - * - * @param node | Node object: cluster to open. + * Draw a line from a node to itself, a circle + * @param {CanvasRenderingContext2D} ctx + * @param {Number} x + * @param {Number} y + * @param {Number} radius + * @private + */ + Edge.prototype._circle = function (ctx, x, y, radius) { + // draw a circle + ctx.beginPath(); + ctx.arc(x, y, radius, 0, 2 * Math.PI, false); + ctx.stroke(); + }; + + /** + * Draw label with white background and with the middle at (x, y) + * @param {CanvasRenderingContext2D} ctx + * @param {String} text + * @param {Number} x + * @param {Number} y + * @private */ - 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; + Edge.prototype._label = function (ctx, text, x, y) { + if (text) { + ctx.font = ((this.from.selected || this.to.selected) ? "bold " : "") + + this.options.fontSize + "px " + this.options.fontFace; + var yLine; - // we decluster until we reach a decent number of nodes - while ((this.nodeIndices.length < this.constants.clustering.initialMaxNodes) && (level < 10)) { - this.decreaseClusterLevel(); - level += 1; - } + if (this.dirtyLabel == true) { + var lines = String(text).split('\n'); + var lineCount = lines.length; + var fontSize = Number(this.options.fontSize); + yLine = y + (1 - lineCount) / 2 * fontSize; - } - else { - this._expandClusterNode(node,false,true); + var width = ctx.measureText(lines[0]).width; + for (var i = 1; i < lineCount; i++) { + var lineWidth = ctx.measureText(lines[i]).width; + width = lineWidth > width ? lineWidth : width; + } + var height = this.options.fontSize * lineCount; + var left = x - width / 2; + var top = y - height / 2; - // update the index list and labels - this._updateNodeIndexList(); - this._updateCalculationNodes(); - this.updateLabels(); - } + // cache + this.labelDimensions = {top:top,left:left,width:width,height:height,yLine:yLine}; + } - // if the simulation was settled, we restart the simulation if a cluster has been formed or expanded - if (this.moving != isMovingBeforeClustering) { - this.start(); + var yLine = this.labelDimensions.yLine; + + ctx.save(); + + if (this.options.labelAlignment != "horizontal"){ + ctx.translate(x, yLine); + this._rotateForLabelAlignment(ctx); + x = 0; + yLine = 0; + } + + + this._drawLabelRect(ctx); + this._drawLabelText(ctx,x,yLine, lines, lineCount, fontSize); + + ctx.restore(); } }; - /** - * This calls the updateClustes with default arguments + * Rotates the canvas so the text is most readable + * @param {CanvasRenderingContext2D} ctx + * @private */ - exports.updateClustersDefault = function() { - if (this.constants.clustering.enabled == true && this.constants.clustering.clusterByZoom == true) { - this.updateClusters(0,false,false); - } - }; + Edge.prototype._rotateForLabelAlignment = function(ctx) { + var dy = this.from.y - this.to.y; + var dx = this.from.x - this.to.x; + var angleInDegrees = Math.atan2(dy, dx); + // rotate so label it is readable + if((angleInDegrees < -1 && dx < 0) || (angleInDegrees > 0 && dx < 0)){ + angleInDegrees = angleInDegrees + Math.PI; + } + + ctx.rotate(angleInDegrees); + }; /** - * 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. + * Draws the label rectangle + * @param {CanvasRenderingContext2D} ctx + * @param {String} labelAlignment + * @private */ - exports.increaseClusterLevel = function() { - this.updateClusters(-1,false,true); - }; + Edge.prototype._drawLabelRect = function(ctx) { + if (this.options.fontFill !== undefined && this.options.fontFill !== null && this.options.fontFill !== "none") { + ctx.fillStyle = this.options.fontFill; + + var lineMargin = 2; + if (this.options.labelAlignment == 'line-center') { + ctx.fillRect(-this.labelDimensions.width * 0.5, -this.labelDimensions.height * 0.5, this.labelDimensions.width, this.labelDimensions.height); + } + else if (this.options.labelAlignment == 'line-above') { + ctx.fillRect(-this.labelDimensions.width * 0.5, -(this.labelDimensions.height + lineMargin), this.labelDimensions.width, this.labelDimensions.height); + } + else if (this.options.labelAlignment == 'line-below') { + ctx.fillRect(-this.labelDimensions.width * 0.5, lineMargin, this.labelDimensions.width, this.labelDimensions.height); + } + else { + ctx.fillRect(this.labelDimensions.left, this.labelDimensions.top, this.labelDimensions.width, this.labelDimensions.height); + } + } + }; /** - * 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. + * Draws the label text + * @param {CanvasRenderingContext2D} ctx + * @param {Number} x + * @param {Number} yLine + * @param {Array} lines + * @param {Number} lineCount + * @param {Number} fontSize + * @private */ - exports.decreaseClusterLevel = function() { - this.updateClusters(1,false,true); - }; + Edge.prototype._drawLabelText = function(ctx, x, yLine, lines, lineCount, fontSize) { + // draw text + ctx.fillStyle = this.options.fontColor || "black"; + ctx.textAlign = "center"; + + // check for label alignment + if (this.options.labelAlignment != 'horizontal') { + var lineMargin = 2; + if (this.options.labelAlignment == 'line-above') { + ctx.textBaseline = "alphabetic"; + yLine -= 2 * lineMargin; // distance from edge, required because we use alphabetic. Alphabetic has less difference between browsers + } + else if (this.options.labelAlignment == 'line-below') { + ctx.textBaseline = "hanging"; + yLine += 2 * lineMargin;// distance from edge, required because we use hanging. Hanging has less difference between browsers + } + else { + ctx.textBaseline = "middle"; + } + } + else { + ctx.textBaseline = "middle"; + } + // check for strokeWidth + if (this.options.fontStrokeWidth > 0){ + ctx.lineWidth = this.options.fontStrokeWidth; + ctx.strokeStyle = this.options.fontStrokeColor; + ctx.lineJoin = 'round'; + } + for (var i = 0; i < lineCount; i++) { + if(this.options.fontStrokeWidth > 0){ + ctx.strokeText(lines[i], x, yLine); + } + ctx.fillText(lines[i], x, yLine); + yLine += fontSize; + } + }; /** - * 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 - * + * 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 */ - exports.updateClusters = function(zoomDirection,recursive,force,doNotStart) { - var isMovingBeforeClustering = this.moving; - var amountOfNodes = this.nodeIndices.length; + Edge.prototype._drawDashLine = function(ctx) { + // set style + ctx.strokeStyle = this._getColor(ctx); + ctx.lineWidth = this._getLineWidth(); + + var via = null; + // only firefox and chrome support this method, else we use the legacy one. + if (ctx.setLineDash !== undefined) { + ctx.save(); + // configure the dash pattern + var pattern = [0]; + if (this.options.dash.length !== undefined && this.options.dash.gap !== undefined) { + pattern = [this.options.dash.length,this.options.dash.gap]; + } + else { + pattern = [5,5]; + } - var detectedZoomingIn = (this.previousScale < this.scale && zoomDirection == 0); - var detectedZoomingOut = (this.previousScale > this.scale && zoomDirection == 0); + // set dash settings for chrome or firefox + ctx.setLineDash(pattern); + ctx.lineDashOffset = 0; - // on zoom out collapse the sector if the scale is at the level the sector was made - if (detectedZoomingOut == true) { - this._collapseSector(); - } + // draw the line + via = this._line(ctx); - // check if we zoom in or out - if (detectedZoomingOut == true || 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); + // restore the dash settings. + ctx.setLineDash([0]); + ctx.lineDashOffset = 0; + ctx.restore(); } - else if (detectedZoomingIn == true || 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 { // unsupporting smooth lines + // draw dashed line + ctx.beginPath(); + ctx.lineCap = 'round'; + if (this.options.dash.altLength !== undefined) //If an alt dash value has been set add to the array this value + { + ctx.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y, + [this.options.dash.length,this.options.dash.gap,this.options.dash.altLength,this.options.dash.gap]); + } + else if (this.options.dash.length !== undefined && this.options.dash.gap !== undefined) //If a dash and gap value has been set add to the array this value + { + ctx.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y, + [this.options.dash.length,this.options.dash.gap]); } - else { - // if a cluster takes up a set percentage of the active window - //this._openClustersBySize(); - this._openClusters(recursive, false); + else //If all else fails draw a line + { + ctx.moveTo(this.from.x, this.from.y); + ctx.lineTo(this.to.x, this.to.y); } - } - this._updateNodeIndexList(); - - // if a cluster was NOT formed and the user zoomed out, we try clustering by hubs - if (this.nodeIndices.length == amountOfNodes && (detectedZoomingOut == true || zoomDirection == -1)) { - this._aggregateHubs(force); - this._updateNodeIndexList(); - } - - // we now reduce chains. - if (detectedZoomingOut == true || zoomDirection == -1) { // zoom out - this.handleChains(); - this._updateNodeIndexList(); - } - - this.previousScale = this.scale; - - // update labels - 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(); + ctx.stroke(); } - 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(); + // draw label + if (this.label) { + var point; + if (this.options.smoothCurves.enabled == true && via != null) { + var midpointX = 0.5*(0.5*(this.from.x + via.x) + 0.5*(this.to.x + via.x)); + var midpointY = 0.5*(0.5*(this.from.y + via.y) + 0.5*(this.to.y + via.y)); + point = {x:midpointX, y:midpointY}; + } + else { + point = this._pointOnLine(0.5); } + this._label(ctx, this.label, point.x, point.y); } - - this._updateCalculationNodes(); }; /** - * This function handles the chains. It is called on every updateClusters(). + * Get a point on a line + * @param {Number} percentage. Value between 0 (line start) and 1 (line end) + * @return {Object} point + * @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) - + 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 } }; /** - * this functions starts clustering by hubs - * The minimum hub threshold is set globally - * + * 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 */ - exports._aggregateHubs = function(force) { - this._getHubSize(); - this._formClustersByHub(force,false); + Edge.prototype._pointOnCircle = function (x, y, radius, percentage) { + var angle = (percentage - 3/8) * 2 * Math.PI; + return { + x: x + radius * Math.cos(angle), + y: y - radius * Math.sin(angle) + } }; - /** - * This function forces hubs to form. - * + * 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 */ - exports.forceAggregateHubs = function(doNotStart) { - var isMovingBeforeClustering = this.moving; - var amountOfNodes = this.nodeIndices.length; - - this._aggregateHubs(true); + Edge.prototype._drawArrowCenter = function(ctx) { + var point; + // set style + ctx.strokeStyle = this._getColor(ctx); + ctx.fillStyle = ctx.strokeStyle; + ctx.lineWidth = this._getLineWidth(); - // update the index list, dynamic edges and labels - this._updateNodeIndexList(); - this.updateLabels(); + if (this.from != this.to) { + // draw line + var via = this._line(ctx); - this._updateCalculationNodes(); + var angle = Math.atan2((this.to.y - this.from.y), (this.to.x - this.from.x)); + var length = (10 + 5 * this.options.width) * this.options.arrowScaleFactor; + // draw an arrow halfway the line + if (this.options.smoothCurves.enabled == true && via != null) { + var midpointX = 0.5*(0.5*(this.from.x + via.x) + 0.5*(this.to.x + via.x)); + var midpointY = 0.5*(0.5*(this.from.y + via.y) + 0.5*(this.to.y + via.y)); + point = {x:midpointX, y:midpointY}; + } + else { + point = this._pointOnLine(0.5); + } - // if a cluster was formed, we increase the clusterSession - if (this.nodeIndices.length != amountOfNodes) { - this.clusterSession += 1; - } + ctx.arrow(point.x, point.y, angle, length); + ctx.fill(); + ctx.stroke(); - 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(); + // draw label + if (this.label) { + this._label(ctx, this.label, point.x, point.y); } } - }; + else { + // draw circle + var x, y; + var radius = 0.25 * Math.max(100,this.physics.springLength); + var node = this.from; + if (!node.width) { + node.resize(ctx); + } + if (node.width > node.height) { + x = node.x + node.width * 0.5; + y = node.y - radius; + } + else { + x = node.x + radius; + y = node.y - node.height * 0.5; + } + this._circle(ctx, x, y, radius); - /** - * If a cluster takes up more than a set percentage of the screen, open the cluster - * - * @private - */ - exports._openClustersBySize = function() { - if (this.constants.clustering.clusterByZoom == true) { - 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); - } - } - } + // draw all arrows + var angle = 0.2 * Math.PI; + var length = (10 + 5 * this.options.width) * this.options.arrowScaleFactor; + point = this._pointOnCircle(x, y, radius, 0.5); + ctx.arrow(point.x, point.y, angle, length); + ctx.fill(); + ctx.stroke(); + + // draw label + if (this.label) { + point = this._pointOnCircle(x, y, radius, 0.5); + this._label(ctx, this.label, point.x, point.y); } } }; + Edge.prototype._pointOnBezier = function(t) { + var via = this._getViaCoordinates(); - /** - * 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._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(); - } - }; + var x = Math.pow(1-t,2)*this.from.x + (2*t*(1 - t))*via.x + Math.pow(t,2)*this.to.x; + var y = Math.pow(1-t,2)*this.from.y + (2*t*(1 - t))*via.y + Math.pow(t,2)*this.to.y; + + return {x:x,y:y}; + } /** - * 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. + * This function uses binary search to look for the point where the bezier curve crosses the border of the node. * - * @param {Node} parentNode | to check for cluster and expand - * @param {Boolean} recursive | enabled or disable recursive calling - * @param {Boolean} force | enabled or disable forcing - * @param {Boolean} [openAll] | This will recursively force all nodes in the parent to be released + * @param from + * @param ctx + * @returns {*} * @private */ - exports._expandClusterNode = function(parentNode, recursive, force, openAll) { - // first check if node is a cluster - if (parentNode.clusterSize > 1) { - if (openAll === undefined) { - openAll = false; - } - // this means that on a double tap event or a zoom event, the cluster fully unpacks if it is smaller than 20 + Edge.prototype._findBorderPosition = function(from,ctx) { + var maxIterations = 10; + var iteration = 0; + var low = 0; + var high = 1; + var pos,angle,distanceToBorder, distanceToNodes, difference; + var threshold = 0.2; + var node = this.to; + if (from == true) { + node = this.from; + } - recursive = openAll || 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]; + while (low <= high && iteration < maxIterations) { + var middle = (low + high) * 0.5; - // 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); - } - } - } + pos = this._pointOnBezier(middle); + angle = Math.atan2((node.y - pos.y), (node.x - pos.x)); + distanceToBorder = node.distanceToBorder(ctx,angle); + distanceToNodes = Math.sqrt(Math.pow(pos.x-node.x,2) + Math.pow(pos.y-node.y,2)); + difference = distanceToBorder - distanceToNodes; + if (Math.abs(difference) < threshold) { + break; // found + } + else if (difference < 0) { // distance to nodes is larger than distance to border --> t needs to be bigger if we're looking at the to node. + if (from == false) { + low = middle; + } + else { + high = middle; + } + } + else { + if (from == false) { + high = middle; + } + else { + low = middle; } } + + iteration++; } + pos.t = middle; + + return pos; }; /** - * 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 + * 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 */ - 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); + Edge.prototype._drawArrow = function(ctx) { + // set style + ctx.strokeStyle = this._getColor(ctx); + ctx.fillStyle = ctx.strokeStyle; + ctx.lineWidth = this._getLineWidth(); - // reconnect rerouted edges to the childNode - this._connectEdgeBackToChild(parentNode,childNode); + // set vars + var angle, length, arrowPos; - // validate all edges in dynamicEdges - this._validateEdges(parentNode); + // if not connected to itself + if (this.from != this.to) { + // draw line + this._line(ctx); - // undo the changes from the clustering operation on the parent node - parentNode.options.mass -= childNode.options.mass; - parentNode.clusterSize -= childNode.clusterSize; - parentNode.options.fontSize = Math.min(this.constants.clustering.maxFontSize, this.constants.nodes.fontSize + this.constants.clustering.fontSizeMultiplier*(parentNode.clusterSize-1)); + // draw arrow head + if (this.options.smoothCurves.enabled == true) { + var via = this._getViaCoordinates(); + arrowPos = this._findBorderPosition(false, ctx); + var guidePos = this._pointOnBezier(Math.max(0.0, arrowPos.t - 0.1)) + angle = Math.atan2((arrowPos.y - guidePos.y), (arrowPos.x - guidePos.x)); + } + else { + 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 toBorderDist = this.to.distanceToBorder(ctx, angle); + var toBorderPoint = (edgeSegmentLength - toBorderDist) / edgeSegmentLength; - // 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()); + arrowPos = {}; + arrowPos.x = (1 - toBorderPoint) * this.from.x + toBorderPoint * this.to.x; + arrowPos.y = (1 - toBorderPoint) * this.from.y + toBorderPoint * this.to.y; + } - // remove node from the list - delete parentNode.containedNodes[containedNodeId]; + // draw arrow at the end of the line + length = (10 + 5 * this.options.width) * this.options.arrowScaleFactor; + ctx.arrow(arrowPos.x,arrowPos.y, angle, length); + ctx.fill(); + ctx.stroke(); - // 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; - } + // draw label + if (this.label) { + var point; + if (this.options.smoothCurves.enabled == true && via != null) { + point = this._pointOnBezier(0.5); + } + 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.physics.springLength); + if (!node.width) { + node.resize(ctx); } - // if there are no others, remove the cluster session from the list - if (othersPresent == false) { - parentNode.clusterSessions.pop(); + 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(); - this._repositionBezierNodes(childNode); - // this._repositionBezierNodes(parentNode); - - // remove the clusterSession from the child node - childNode.clusterSession = 0; - - // recalculate the size of the node on the next time the node is rendered - parentNode.clearSizeCache(); - - // restart the simulation to reorganise all nodes - this.moving = true; - } + // draw all arrows + var length = (10 + 5 * this.options.width) * this.options.arrowScaleFactor; + ctx.arrow(arrow.x, arrow.y, arrow.angle, length); + ctx.fill(); + ctx.stroke(); - // check if a further expansion step is possible if recursivity is enabled - if (recursive == true) { - this._expandClusterNode(childNode,recursive,force,openAll); + // draw label + if (this.label) { + point = this._pointOnCircle(x, y, radius, 0.5); + this._label(ctx, this.label, point.x, point.y); + } } }; - /** - * position the bezier nodes at the center of the edges - * - * @param node + * 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 */ - exports._repositionBezierNodes = function(node) { - for (var i = 0; i < node.dynamicEdges.length; i++) { - node.dynamicEdges[i].positionBezierNode(); + Edge.prototype._getDistanceToEdge = function (x1,y1, x2,y2, x3,y3) { // x3,y3 is the point + var returnValue = 0; + if (this.from != this.to) { + if (this.options.smoothCurves.enabled == true) { + var xVia, yVia; + if (this.options.smoothCurves.enabled == true && this.options.smoothCurves.dynamic == true) { + xVia = this.via.x; + yVia = this.via.y; + } + else { + var via = this._getViaCoordinates(); + xVia = via.x; + yVia = via.y; + } + var minDistance = 1e9; + var distance; + var i,t,x,y, lastX, lastY; + for (i = 0; i < 10; i++) { + t = 0.1*i; + x = Math.pow(1-t,2)*x1 + (2*t*(1 - t))*xVia + Math.pow(t,2)*x2; + y = Math.pow(1-t,2)*y1 + (2*t*(1 - t))*yVia + Math.pow(t,2)*y2; + if (i > 0) { + distance = this._getDistanceToLine(lastX,lastY,x,y, x3,y3); + minDistance = distance < minDistance ? distance : minDistance; + } + lastX = x; lastY = y; + } + returnValue = minDistance; + } + else { + returnValue = this._getDistanceToLine(x1,y1,x2,y2,x3,y3); + } } - }; - - - /** - * 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) { - if (this.constants.clustering.clusterByZoom == true) { - this._formClustersByZoom(); + else { + var x, y, dx, dy; + var radius = 0.25 * this.physics.springLength; + var node = this.from; + if (node.width > node.height) { + x = node.x + 0.5 * node.width; + y = node.y - radius; + } + else { + x = node.x + radius; + y = node.y - 0.5 * node.height; } + dx = x - x3; + dy = y - y3; + returnValue = Math.abs(Math.sqrt(dx*dx + dy*dy) - radius); + } + + if (this.labelDimensions.left < x3 && + this.labelDimensions.left + this.labelDimensions.width > x3 && + this.labelDimensions.top < y3 && + this.labelDimensions.top + this.labelDimensions.height > y3) { + return 0; } else { - this._forceClustersByZoom(); + return returnValue; } }; + 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; - /** - * This function handles the clustering by zooming out, this is based on a minimum edge distance - * - * @private - */ - exports._formClustersByZoom = function() { - var dx,dy,length; - var minLength = this.constants.clustering.clusterEdgeThreshold/this.scale; + if (u > 1) { + u = 1; + } + else if (u < 0) { + u = 0; + } - // check if any edges are shorter than minLength and start the clustering - // the clustering favours the node with the larger mass - for (var edgeId in this.edges) { - if (this.edges.hasOwnProperty(edgeId)) { - var edge = this.edges[edgeId]; - if (edge.connected) { - if (edge.toId != edge.fromId) { - dx = (edge.to.x - edge.from.x); - dy = (edge.to.y - edge.from.y); - length = Math.sqrt(dx * dx + dy * dy); - - - if (length < minLength) { - // first check which node is larger - var parentNode = edge.from; - var childNode = edge.to; - if (edge.to.options.mass > edge.from.options.mass) { - parentNode = edge.to; - childNode = edge.from; - } + var x = x1 + u * px, + y = y1 + u * py, + dx = x - x3, + dy = y - y3; - if (childNode.dynamicEdges.length == 1) { - this._addToCluster(parentNode,childNode,false); - } - else if (parentNode.dynamicEdges.length == 1) { - this._addToCluster(childNode,parentNode,false); - } - } - } - } - } - } + //# Note: If the actual distance does not matter, + //# if you only want to compare what this function + //# returns to other results of this function, you + //# can just return the squared distance instead + //# (i.e. remove the sqrt) to gain a little performance + + return Math.sqrt(dx*dx + dy*dy); }; /** - * This function forces the network to cluster all nodes with only one connecting edge to their - * connected node. + * This allows the zoom level of the network to influence the rendering * - * @private + * @param scale */ - 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.dynamicEdges.length == 1) { - var edge = childNode.dynamicEdges[0]; - var parentNode = (edge.toId == childNode.id) ? this.nodes[edge.fromId] : this.nodes[edge.toId]; - // group to the largest node - if (childNode.id != parentNode.id) { - if (parentNode.options.mass > childNode.options.mass) { - this._addToCluster(parentNode,childNode,true); - } - else { - this._addToCluster(childNode,parentNode,true); - } - } - } - } - } + Edge.prototype.setScale = function(scale) { + this.networkScaleInv = 1.0/scale; }; - /** - * To keep the nodes of roughly equal size we normalize the cluster levels. - * This function clusters a node to its smallest connected neighbour. - * - * @param node - * @private - */ - exports._clusterToSmallestNeighbour = function(node) { - var smallestNeighbour = -1; - var smallestNeighbourNode = null; - for (var i = 0; i < node.dynamicEdges.length; i++) { - if (node.dynamicEdges[i] !== undefined) { - var neighbour = null; - if (node.dynamicEdges[i].fromId != node.id) { - neighbour = node.dynamicEdges[i].from; - } - else if (node.dynamicEdges[i].toId != node.id) { - neighbour = node.dynamicEdges[i].to; - } + Edge.prototype.select = function() { + this.selected = true; + }; + Edge.prototype.unselect = function() { + this.selected = false; + }; - if (neighbour != null && smallestNeighbour > neighbour.clusterSessions.length) { - smallestNeighbour = neighbour.clusterSessions.length; - smallestNeighbourNode = neighbour; - } - } + Edge.prototype.positionBezierNode = function() { + if (this.via !== null && this.from !== null && this.to !== null) { + this.via.x = 0.5 * (this.from.x + this.to.x); + this.via.y = 0.5 * (this.from.y + this.to.y); } - - if (neighbour != null && this.nodes[neighbour.id] !== undefined) { - this._addToCluster(neighbour, node, true); + else if (this.via !== null) { + this.via.x = 0; + this.via.y = 0; } }; - /** - * This function forms clusters from hubs, it loops over all nodes - * - * @param {Boolean} force | Disregard zoom level - * @param {Boolean} onlyEqual | This only clusters a hub with a specific number of edges - * @private + * This function draws the control nodes for the manipulator. + * In order to enable this, only set the this.controlNodesEnabled to true. + * @param ctx */ - 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); + 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:7, borderWidth:2, borderWidthSelected: 2}, + physics:{damping:0}, + clustering: {maxNodeSizeIncrements: 0 ,nodeScaling: {width:0, height: 0, radius:0}} + }; + this.controlNodes.from = new Node( + {id:nodeIdFrom, + shape:'dot', + color:{background:'#ff0000', border:'#3c3c3c', highlight: {background:'#07f968'}} + },{},{},constants); + this.controlNodes.to = new Node( + {id:nodeIdTo, + shape:'dot', + color:{background:'#ff0000', border:'#3c3c3c', highlight: {background:'#07f968'}} + },{},{},constants); + } + + this.controlNodes.positions = {}; + if (this.controlNodes.from.selected == false) { + this.controlNodes.positions.from = this.getControlNodeFromPosition(ctx); + this.controlNodes.from.x = this.controlNodes.positions.from.x; + this.controlNodes.from.y = this.controlNodes.positions.from.y; + } + if (this.controlNodes.to.selected == false) { + this.controlNodes.positions.to = this.getControlNodeToPosition(ctx); + this.controlNodes.to.x = this.controlNodes.positions.to.x; + this.controlNodes.to.y = this.controlNodes.positions.to.y; } + + this.controlNodes.from.draw(ctx); + this.controlNodes.to.draw(ctx); + } + else { + this.controlNodes = {from:null, to:null, positions:{}}; } }; /** - * 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] | + * Enable control nodes. * @private - */ - exports._formClusterFromHub = function(hubNode, force, onlyEqual, absorptionSizeOffset) { - if (absorptionSizeOffset === undefined) { - absorptionSizeOffset = 0; - } - //this.hubThreshold = 43 - //if (hubNode.dynamicEdgesLength < 0) { - // console.error(hubNode.dynamicEdgesLength, this.hubThreshold, onlyEqual) - //} - // we decide if the node is a hub - if ((hubNode.dynamicEdges.length >= this.hubThreshold && onlyEqual == false) || - (hubNode.dynamicEdges.length == this.hubThreshold && onlyEqual == true)) { - // initialize variables - var dx,dy,length; - var minLength = this.constants.clustering.clusterEdgeThreshold/this.scale; - var allowCluster = false; - - // we create a list of edges because the dynamicEdges change over the course of this loop - var edgesIdarray = []; - var amountOfInitialEdges = hubNode.dynamicEdges.length; - for (var j = 0; j < amountOfInitialEdges; j++) { - edgesIdarray.push(hubNode.dynamicEdges[j].id); - } - - // if the hub clustering is not forced, 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) { - var children = []; - var childrenIds = {}; - // we loop over all edges INITIALLY connected to this hub to get a list of the childNodes - for (j = 0; j < amountOfInitialEdges; j++) { - edge = this.edges[edgesIdarray[j]]; - var childNode = this.nodes[(edge.fromId == hubNode.id) ? edge.toId : edge.fromId]; - if (childrenIds[childNode.id] === undefined) { - childrenIds[childNode.id] = true; - children.push(childNode); - } - } - - for (j = 0; j < children.length; j++) { - var childNode = children[j]; - // we do not want hubs to merge with other hubs nor do we want to cluster itself. - if ((childNode.dynamicEdges.length <= (this.hubThreshold + absorptionSizeOffset)) && - (childNode.id != hubNode.id)) { - this._addToCluster(hubNode,childNode,force); - - } - else { - //console.log("WILL NOT MERGE:",childNode.dynamicEdges.length , (this.hubThreshold + absorptionSizeOffset)) - } - } - - } - } + */ + Edge.prototype._enableControlNodes = function() { + this.fromBackup = this.from; + this.toBackup = this.to; + this.controlNodesEnabled = true; }; - - /** - * This function adds the child node to the parent node, creating a cluster if it is not already. - * - * @param {Node} parentNode | this is the node that will house the child node - * @param {Node} childNode | this node will be deleted from the global this.nodes and stored in the parent node - * @param {Boolean} force | true will only update the remainingEdges at the very end of the clustering, ensuring single level collapse + * disable control nodes and remove from dynamicEdges from old node * @private */ - exports._addToCluster = function(parentNode, childNode, force) { - // join child node in the parent node - parentNode.containedNodes[childNode.id] = childNode; - //console.log(parentNode.id, childNode.id) - // 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 - //console.log("COLLECT",parentNode.id, childNode.id, edge.toId, edge.fromId) - this._addToContainedEdges(parentNode,childNode,edge); - } - else { - //console.log("REWIRE",parentNode.id, childNode.id, edge.toId, edge.fromId) - this._connectEdgeToCluster(parentNode,childNode,edge); - } + Edge.prototype._disableControlNodes = function() { + this.fromId = this.from.id; + this.toId = this.to.id; + if (this.fromId != this.fromBackup.id) { // from was changed, remove edge from old 'from' node dynamic edges + this.fromBackup.detachEdge(this); + } + else if (this.toId != this.toBackup.id) { // to was changed, remove edge from old 'to' node dynamic edges + this.toBackup.detachEdge(this); } - // a contained node has no dynamic edges. - childNode.dynamicEdges = []; - - // remove circular edges from clusters - this._containCircularEdgesFromNode(parentNode,childNode); + this.fromBackup = null; + this.toBackup = null; + this.controlNodesEnabled = false; + }; - // remove the childNode from the global nodes object - delete this.nodes[childNode.id]; - // update the properties of the child and parent - var massBefore = parentNode.options.mass; - childNode.clusterSession = this.clusterSession; - parentNode.options.mass += childNode.options.mass; - parentNode.clusterSize += childNode.clusterSize; - parentNode.options.fontSize = Math.min(this.constants.clustering.maxFontSize, this.constants.nodes.fontSize + this.constants.clustering.fontSizeMultiplier*parentNode.clusterSize); + /** + * This checks if one of the control nodes is selected and if so, returns the control node object. Else it returns null. + * @param x + * @param y + * @returns {null} + * @private + */ + Edge.prototype._getSelectedControlNode = function(x,y) { + var positions = this.controlNodes.positions; + var fromDistance = Math.sqrt(Math.pow(x - positions.from.x,2) + Math.pow(y - positions.from.y,2)); + var toDistance = Math.sqrt(Math.pow(x - positions.to.x ,2) + Math.pow(y - positions.to.y ,2)); - // 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); + if (fromDistance < 15) { + this.connectedNode = this.from; + this.from = this.controlNodes.from; + return this.controlNodes.from; } - - // forced clusters only open from screen size and double tap - if (force == true) { - parentNode.formationScale = 0; + else if (toDistance < 15) { + this.connectedNode = this.to; + this.to = this.controlNodes.to; + return this.controlNodes.to; } else { - parentNode.formationScale = this.scale; // The latest child has been added on this scale + return null; } - - // 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 adds an edge from the childNode to the contained edges of the parent node - * - * @param parentNode | Node object - * @param childNode | Node object - * @param edge | Edge object + * this resets the control nodes to their original position. * @private */ - exports._addToContainedEdges = function(parentNode, childNode, edge) { - // create an array object if it does not yet exist for this childNode - if (parentNode.containedEdges[childNode.id] === undefined) { - parentNode.containedEdges[childNode.id] = [] + Edge.prototype._restoreControlNodes = function() { + if (this.controlNodes.from.selected == true) { + this.from = this.connectedNode; + this.connectedNode = null; + this.controlNodes.from.unselect(); } - // add this edge to the list - parentNode.containedEdges[childNode.id].push(edge); - - // remove the edge from the global edges object - delete this.edges[edge.id]; - - // remove the edge from the parent object - for (var i = 0; i < parentNode.dynamicEdges.length; i++) { - if (parentNode.dynamicEdges[i].id == edge.id) { - parentNode.dynamicEdges.splice(i,1); - break; - } + else if (this.controlNodes.to.selected == true) { + this.to = this.connectedNode; + this.connectedNode = null; + this.controlNodes.to.unselect(); } }; /** - * 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. + * this calculates the position of the control nodes on the edges of the parent nodes. * - * @param {Node} parentNode | Node object - * @param {Node} childNode | Node object - * @param {Edge} edge | Edge object - * @private + * @param ctx + * @returns {x: *, y: *} */ - exports._connectEdgeToCluster = function(parentNode, childNode, edge) { - // handle circular edges - if (edge.toId == edge.fromId) { - this._addToContainedEdges(parentNode, childNode, edge); + Edge.prototype.getControlNodeFromPosition = function(ctx) { + // draw arrow head + var controlnodeFromPos; + if (this.options.smoothCurves.enabled == true) { + controlnodeFromPos = this._findBorderPosition(true, ctx); } else { - if (edge.toId == childNode.id) { // edge connected to other node on the "to" side - edge.originalToId.push(childNode.id); - edge.to = parentNode; - edge.toId = parentNode.id; - } - else { // edge connected to other node with the "from" side - edge.originalFromId.push(childNode.id); - edge.from = parentNode; - edge.fromId = parentNode.id; - } + 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); - this._addToReroutedEdges(parentNode,childNode,edge); + var fromBorderDist = this.from.distanceToBorder(ctx, angle + Math.PI); + var fromBorderPoint = (edgeSegmentLength - fromBorderDist) / edgeSegmentLength; + controlnodeFromPos = {}; + controlnodeFromPos.x = (fromBorderPoint) * this.from.x + (1 - fromBorderPoint) * this.to.x; + controlnodeFromPos.y = (fromBorderPoint) * this.from.y + (1 - fromBorderPoint) * this.to.y; } - }; + return controlnodeFromPos; + }; /** - * 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 calculates the position of the control nodes on the edges of the parent nodes. * - * @param parentNode - * @param childNode - * @private + * @param ctx + * @returns {{from: {x: number, y: number}, to: {x: *, y: *}}} */ - 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); - } + Edge.prototype.getControlNodeToPosition = function(ctx) { + // draw arrow head + var controlnodeFromPos,controlnodeToPos; + if (this.options.smoothCurves.enabled == true) { + controlnodeToPos = this._findBorderPosition(false, ctx); } - }; - + else { + 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 toBorderDist = this.to.distanceToBorder(ctx, angle); + var toBorderPoint = (edgeSegmentLength - toBorderDist) / edgeSegmentLength; - /** - * This adds an edge from the childNode to the rerouted edges of the parent node - * - * @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] = []; + controlnodeToPos = {}; + controlnodeToPos.x = (1 - toBorderPoint) * this.from.x + toBorderPoint * this.to.x; + controlnodeToPos.y = (1 - toBorderPoint) * this.from.y + toBorderPoint * this.to.y; } - parentNode.reroutedEdges[childNode.id].push(edge); - // this edge becomes part of the dynamicEdges of the cluster node - parentNode.dynamicEdges.push(edge); - }; + return controlnodeToPos; + }; + module.exports = Edge; +/***/ }, +/* 58 */ +/***/ function(module, exports, __webpack_require__) { /** - * This function connects an edge that was connected to a cluster node back to the child node. - * - * @param parentNode | Node object - * @param childNode | Node object - * @private + * 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. */ - exports._connectEdgeBackToChild = function(parentNode, childNode) { - if (parentNode.reroutedEdges.hasOwnProperty(childNode.id)) { - for (var i = 0; i < parentNode.reroutedEdges[childNode.id].length; i++) { - var edge = parentNode.reroutedEdges[childNode.id][i]; - if (edge.originalFromId[edge.originalFromId.length-1] == childNode.id) { - edge.originalFromId.pop(); - edge.fromId = childNode.id; - edge.from = childNode; - } - else { - edge.originalToId.pop(); - edge.toId = childNode.id; - edge.to = childNode; - } - - // append this edge to the list of edges connecting to the childnode - childNode.dynamicEdges.push(edge); + function Popup(container, x, y, text, style) { + if (container) { + this.container = container; + } + else { + this.container = document.body; + } - // 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; + // 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' } } } - // remove the entry from the rerouted edges - delete parentNode.reroutedEdges[childNode.id]; } - }; + this.x = 0; + this.y = 0; + this.padding = 5; + this.hidden = false; - /** - * When loops are clustered, an edge can be both in the rerouted array and the contained array. - * This function is called last to verify that all edges in dynamicEdges are in fact connected to the - * parentNode - * - * @param parentNode | Node object - * @private - */ - exports._validateEdges = function(parentNode) { - var dynamicEdges = [] - for (var i = 0; i < parentNode.dynamicEdges.length; i++) { - var edge = parentNode.dynamicEdges[i]; - if (parentNode.id == edge.toId || parentNode.id == edge.fromId) { - dynamicEdges.push(edge); - } + if (x !== undefined && y !== undefined) { + this.setPosition(x, y); + } + if (text !== undefined) { + this.setText(text); } - parentNode.dynamicEdges = dynamicEdges; - }; + // create the frame + this.frame = document.createElement('div'); + this.frame.className = 'network-tooltip'; + this.frame.style.color = style.fontColor; + this.frame.style.backgroundColor = style.color.background; + this.frame.style.borderColor = style.color.border; + this.frame.style.fontSize = style.fontSize + 'px'; + this.frame.style.fontFamily = style.fontFace; + this.container.appendChild(this.frame); + } /** - * 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 + * @param {number} x Horizontal position of the popup window + * @param {number} y Vertical position of the popup window */ - 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]; - + Popup.prototype.setPosition = function(x, y) { + this.x = parseInt(x); + this.y = parseInt(y); }; - - - - // ------------------- UTILITY FUNCTIONS ---------------------------- // - - /** - * This updates the node labels for all nodes (for debugging purposes) + * Set the content for the popup window. This can be HTML code or text. + * @param {string | Element} content */ - 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),"]"); - } - } + Popup.prototype.setText = function(content) { + if (content instanceof Element) { + this.frame.innerHTML = ''; + this.frame.appendChild(content); } - - // update node labels - for (nodeId in this.nodes) { - if (this.nodes.hasOwnProperty(nodeId)) { - node = this.nodes[nodeId]; - if (node.clusterSize == 1) { - if (node.originalLabel !== undefined) { - node.label = node.originalLabel; - } - else { - node.label = String(node.id); - } - } - } + else { + this.frame.innerHTML = content; // string containing text or HTML } - - // /* Debug Override */ - // for (nodeId in this.nodes) { - // if (this.nodes.hasOwnProperty(nodeId)) { - // node = this.nodes[nodeId]; - // node.label = String(node.clusterSize + ":" + node.dynamicEdges.length); - // } - // } - }; - /** - * 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. + * Show the popup window + * @param {boolean} show Optional. Show or hide the window */ - exports.normalizeClusterLevels = function() { - var maxLevel = 0; - var minLevel = 1e9; - var clusterLevel = 0; - var nodeId; + Popup.prototype.show = function (show) { + if (show === undefined) { + show = true; + } - // 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 (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; } - } - 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]); - } - } + var left = this.x; + if (left + width + this.padding > maxWidth) { + left = maxWidth - width - this.padding; } - this._updateNodeIndexList(); - // if a cluster was formed, we increase the clusterSession - if (this.nodeIndices.length != amountOfNodes) { - this.clusterSession += 1; + 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.hidden = false; + } + else { + this.hide(); } }; - - /** - * 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 + * Hide the popup window */ - 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 - ) + Popup.prototype.hide = function () { + this.hidden = true; + this.frame.style.visibility = "hidden"; }; + module.exports = Popup; - /** - * 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. - * - */ - exports.repositionNodes = function() { - for (var i = 0; i < this.nodeIndices.length; i++) { - var node = this.nodes[this.nodeIndices[i]]; - if ((node.xFixed == false || node.yFixed == false)) { - var radius = 10 * 0.1*this.nodeIndices.length * Math.min(100,node.options.mass); - var angle = 2 * Math.PI * Math.random(); - if (node.xFixed == false) {node.x = radius * Math.cos(angle);} - if (node.yFixed == false) {node.y = radius * Math.sin(angle);} - this._repositionBezierNodes(node); - } - } - }; +/***/ }, +/* 59 */ +/***/ function(module, exports, __webpack_require__) { + + var PhysicsMixin = __webpack_require__(60); + var ClusterMixin = __webpack_require__(64); + var SectorsMixin = __webpack_require__(65); + var SelectionMixin = __webpack_require__(66); + var ManipulationMixin = __webpack_require__(67); + var NavigationMixin = __webpack_require__(68); + var HierarchicalLayoutMixin = __webpack_require__(69); /** - * 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%) + * Load a mixin into the network object * + * @param {Object} sourceVariable | this object has to contain functions. * @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.dynamicEdges.length > largestHub) { - largestHub = node.dynamicEdges.length; + exports._loadMixin = function (sourceVariable) { + for (var mixinFunction in sourceVariable) { + if (sourceVariable.hasOwnProperty(mixinFunction)) { + this[mixinFunction] = sourceVariable[mixinFunction]; } - average += node.dynamicEdges.length; - averageSquared += Math.pow(node.dynamicEdges.length,2); - hubCounter += 1; - } - average = average / hubCounter; - averageSquared = averageSquared / hubCounter; - - var variance = averageSquared - Math.pow(average,2); - - var standardDeviation = Math.sqrt(variance); - - this.hubThreshold = Math.floor(average + 2*standardDeviation); - - // always have at least one to cluster - if (this.hubThreshold > largestHub) { - this.hubThreshold = largestHub; } - - // 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. + * removes a mixin from the network object. * - * @param {Number} fraction | between 0 and 1, the percentage of chains to reduce + * @param {Object} sourceVariable | this object has to contain functions. * @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].dynamicEdges.length == 2) { - if (reduceAmount > 0) { - this._formClusterFromHub(this.nodes[nodeId],true,true,1); - reduceAmount -= 1; - } - } + exports._clearMixin = function (sourceVariable) { + for (var mixinFunction in sourceVariable) { + if (sourceVariable.hasOwnProperty(mixinFunction)) { + this[mixinFunction] = undefined; } } }; + /** - * 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. + * Mixin the physics system and initialize the parameters required. * * @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].dynamicEdges.length == 2) { - chains += 1; - } - total += 1; - } + exports._loadPhysicsSystem = function () { + this._loadMixin(PhysicsMixin); + this._loadSelectedForceSolver(); + if (this.constants.configurePhysics == true) { + this._loadPhysicsConfiguration(); + } + else { + this._cleanupPhysicsConfiguration(); } - return chains/total; }; -/***/ }, -/* 61 */ -/***/ function(module, exports, __webpack_require__) { - - var util = __webpack_require__(1); - var Node = __webpack_require__(40); - - /** - * Creation of the SectorMixin var. - * - * This contains all the functions the Network object can use to employ the sector system. - * The sector system is always used by Network, though the benefits only apply to the use of clustering. - * If clustering is not used, there is no overhead except for a duplicate object with references to nodes and edges. - */ - /** - * This function is only called by the setData function of the Network object. - * This loads the global references into the active sector. This initializes the sector. + * Mixin the cluster system and initialize the parameters required. * * @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._loadClusterSystem = function () { + this.clusterSession = 0; + this.hubThreshold = 5; + this._loadMixin(ClusterMixin); }; /** - * /** - * 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 + * Mixin the sector system and initialize the parameters required * - * @param {String} sectorId - * @param {String} [sectorType] | "active" or "frozen" * @private */ - exports._switchToSector = function(sectorId, sectorType) { - if (sectorType === undefined || sectorType == "active") { - this._switchToActiveSector(sectorId); - } - else { - this._switchToFrozenSector(sectorId); - } + 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); }; /** - * This function sets the global references to nodes, edges and nodeIndices back to - * those of the supplied active sector. + * Mixin the selection system and initialize the parameters required * - * @param sectorId * @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._loadSelectionSystem = function () { + this.selectionObj = {nodes: {}, edges: {}}; + + this._loadMixin(SelectionMixin); }; /** - * This function sets the global references to nodes, edges and nodeIndices back to - * those of the supplied active sector. + * Mixin the navigationUI (User Interface) system and initialize the parameters required * * @private */ - exports._switchToSupportSector = function() { - this.nodeIndices = this.sectors["support"]["nodeIndices"]; - this.nodes = this.sectors["support"]["nodes"]; - this.edges = this.sectors["support"]["edges"]; + 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'; + if (this.editMode == true) { + this.manipulationDiv.style.display = "block"; + } + else { + this.manipulationDiv.style.display = "none"; + } + this.frame.appendChild(this.manipulationDiv); + } + + if (this.editModeDiv === undefined) { + this.editModeDiv = document.createElement('div'); + this.editModeDiv.className = 'network-manipulation-editMode'; + if (this.editMode == true) { + this.editModeDiv.style.display = "none"; + } + else { + this.editModeDiv.style.display = "block"; + } + this.frame.appendChild(this.editModeDiv); + } + + if (this.closeDiv === undefined) { + this.closeDiv = document.createElement('div'); + this.closeDiv.className = 'network-manipulation-closeDiv'; + this.closeDiv.style.display = this.manipulationDiv.style.display; + this.frame.appendChild(this.closeDiv); + } + + // load the manipulation functions + this._loadMixin(ManipulationMixin); + + // create the manipulator toolbar + this._createManipulatorBar(); + } + else { + if (this.manipulationDiv !== undefined) { + // removes all the bindings and overloads + this._createManipulatorBar(); + + // remove the manipulation divs + this.frame.removeChild(this.manipulationDiv); + this.frame.removeChild(this.editModeDiv); + this.frame.removeChild(this.closeDiv); + + this.manipulationDiv = undefined; + this.editModeDiv = undefined; + this.closeDiv = undefined; + // remove the mixin functions + this._clearMixin(ManipulationMixin); + } + } }; /** - * This function sets the global references to nodes, edges and nodeIndices back to - * those of the supplied frozen sector. + * Mixin the navigation (User Interface) system and initialize the parameters required * - * @param sectorId * @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._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(); + } }; /** - * This function sets the global references to nodes, edges and nodeIndices back to - * those of the currently active sector. + * Mixin the hierarchical layout system. * * @private */ - exports._loadLatestSector = function() { - this._switchToSector(this._sector()); + exports._loadHierarchySystem = function () { + this._loadMixin(HierarchicalLayoutMixin); }; +/***/ }, +/* 60 */ +/***/ function(module, exports, __webpack_require__) { + + var util = __webpack_require__(1); + var RepulsionMixin = __webpack_require__(61); + var HierarchialRepulsionMixin = __webpack_require__(62); + var BarnesHutMixin = __webpack_require__(63); + /** - * This function returns the currently active sector Id + * Toggling barnes Hut calculation on and off. * - * @returns {String} * @private */ - exports._sector = function() { - return this.activeSector[this.activeSector.length-1]; + exports._toggleBarnesHut = function () { + this.constants.physics.barnesHut.enabled = !this.constants.physics.barnesHut.enabled; + this._loadSelectedForceSolver(); + this.moving = true; + this.start(); }; /** - * This function returns the previously active sector Id + * This loads the node force solver based on the barnes hut or repulsion algorithm * - * @returns {String} * @private */ - exports._previousSector = function() { - if (this.activeSector.length > 1) { - return this.activeSector[this.activeSector.length-2]; + 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); + + 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 { - throw new TypeError('there are not enough sectors in the this.activeSector array.'); + 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); } }; - /** - * 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. + * 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. * - * @param newId * @private */ - exports._setActiveSector = function(newId) { - this.activeSector.push(newId); + 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 { + // we now start the force calculation + this._calculateForces(); + } }; /** - * We remove the currently active sector id from the active sector stack. This happens when - * we reactivate the previously active sector - * + * Calculate the external forces acting on the nodes + * Forces are caused by: edges, repulsing forces between nodes, gravity * @private */ - exports._forgetLastSector = function() { - this.activeSector.pop(); + exports._calculateForces = function () { + // Gravity is required to keep separated groups from floating off + // the forces are reset to zero in this loop by using _setForce instead + // of _addForce + + this._calculateGravitationalForces(); + this._calculateNodeForces(); + + if (this.constants.physics.springConstant > 0) { + if (this.constants.smoothCurves.enabled == true && this.constants.smoothCurves.dynamic == true) { + this._calculateSpringForcesWithSupport(); + } + else { + if (this.constants.physics.hierarchicalRepulsion.enabled == true) { + this._calculateHierarchicalSpringForces(); + } + else { + this._calculateSpringForces(); + } + } + } }; /** - * This function creates a new active sector with the supplied newId. This newId - * is the expanding node id. + * 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. * - * @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}; + exports._updateCalculationNodes = function () { + if (this.constants.smoothCurves.enabled == true && this.constants.smoothCurves.dynamic == true) { + this.calculationNodes = {}; + this.calculationNodeIndices = []; - // 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" + 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]; } - },{},{},this.constants); - this.sectors["active"][newId]['drawingNode'].clusterSize = 2; + else { + supportNodes[supportNodeId]._setForce(0, 0); + } + } + } + + for (var idx in this.calculationNodes) { + if (this.calculationNodes.hasOwnProperty(idx)) { + this.calculationNodeIndices.push(idx); + } + } + } + else { + this.calculationNodes = this.nodes; + this.calculationNodeIndices = this.nodeIndices; + } }; /** - * This function removes the currently active sector. This is called when we create a new - * active sector. + * this function applies the central gravity effect to keep groups from floating off * - * @param {String} sectorId | Id of the active sector that will be removed * @private */ - exports._deleteActiveSector = function(sectorId) { - delete this.sectors["active"][sectorId]; - }; + exports._calculateGravitationalForces = function () { + var dx, dy, distance, node, i; + var nodes = this.calculationNodes; + var gravity = this.constants.physics.centralGravity; + var gravityForce = 0; + for (i = 0; i < this.calculationNodeIndices.length; i++) { + node = nodes[this.calculationNodeIndices[i]]; + node.damping = this.constants.physics.damping; // possibly add function to alter damping properties of clusters. + // gravity does not apply when we are in a pocket sector + if (this._sector() == "default" && gravity != 0) { + dx = -node.x; + dy = -node.y; + distance = Math.sqrt(dx * dx + dy * dy); - /** - * 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]; + gravityForce = (distance == 0) ? 0 : (gravity / distance); + node.fx = dx * gravityForce; + node.fy = dy * gravityForce; + } + else { + node.fx = 0; + node.fy = 0; + } + } }; + + /** - * 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 function calculates the effects of the springs in the case of unsmooth curves. * - * @param sectorId * @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._calculateSpringForces = function () { + var edgeLength, edge, edgeId; + var dx, dy, fx, fy, springForce, distance; + var edges = this.edges; - // we have moved the sector data into the frozen set, we now remove it from the active set - this._deleteActiveSector(sectorId); - }; + // forces caused by the edges, modelled as springs + for (edgeId in edges) { + if (edges.hasOwnProperty(edgeId)) { + edge = edges[edgeId]; + if (edge.connected === true) { + // only calculate forces if nodes are in the same sector + if (this.nodes.hasOwnProperty(edge.toId) && this.nodes.hasOwnProperty(edge.fromId)) { + edgeLength = edge.physics.springLength; + dx = (edge.from.x - edge.to.x); + dy = (edge.from.y - edge.to.y); + distance = Math.sqrt(dx * dx + dy * dy); - /** - * 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]; + if (distance == 0) { + distance = 0.01; + } - // we have moved the sector data into the active set, we now remove it from the frozen stack - this._deleteFrozenSector(sectorId); - }; + // 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; - /** - * 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]; + edge.from.fx += fx; + edge.from.fy += fy; + edge.to.fx -= fx; + edge.to.fy -= fy; + } + } } } + }; - // 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]; - } - } - // merge the nodeIndices - for (var i = 0; i < this.nodeIndices.length; i++) { - this.sectors["frozen"][sectorId]["nodeIndices"].push(this.nodeIndices[i]); - } - }; /** - * 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. + * This function calculates the springforces on the nodes, accounting for the support nodes. * * @private */ - exports._collapseThisToSingleCluster = function() { - this.clusterToFit(1,false); + exports._calculateSpringForcesWithSupport = function () { + var edgeLength, edge, edgeId; + 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 === true) { + // only calculate forces if nodes are in the same sector + if (this.nodes.hasOwnProperty(edge.toId) && this.nodes.hasOwnProperty(edge.fromId)) { + if (edge.via != null) { + var node1 = edge.to; + var node2 = edge.via; + var node3 = edge.from; + + edgeLength = edge.physics.springLength; + + this._calculateSpringForce(node1, node2, 0.5 * edgeLength); + this._calculateSpringForce(node2, node3, 0.5 * edgeLength); + } + } + } + } + } }; /** - * We create a new active sector from the node that we want to open. + * This is the code actually performing the calculation for the function above. It is split out to avoid repetition. * - * @param node + * @param node1 + * @param node2 + * @param edgeLength * @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!!"); - // } + exports._calculateSpringForce = function (node1, node2, edgeLength) { + var dx, dy, fx, fy, springForce, distance; - // 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]; + dx = (node1.x - node2.x); + dy = (node1.y - node2.y); + distance = Math.sqrt(dx * dx + dy * dy); - var unqiueIdentifier = util.randomUUID(); + if (distance == 0) { + distance = 0.01; + } - // we fully freeze the currently active sector - this._freezeSector(sector); + // the 1/distance is so the fx and fy can be calculated without sine or cosine. + springForce = this.constants.physics.springConstant * (edgeLength - distance) / distance; - // we create a new active sector. This sector has the Id of the node to ensure uniqueness - this._createNewSector(unqiueIdentifier); + fx = dx * springForce; + fy = dy * springForce; - // we add the active sector to the sectors array to be able to revert these steps later on - this._setActiveSector(unqiueIdentifier); + node1.fx += fx; + node1.fy += fy; + node2.fx -= fx; + node2.fy -= fy; + }; - // 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._cleanupPhysicsConfiguration = function() { + if (this.physicsConfiguration !== undefined) { + while (this.physicsConfiguration.hasChildNodes()) { + this.physicsConfiguration.removeChild(this.physicsConfiguration.firstChild); + } + this.physicsConfiguration.parentNode.removeChild(this.physicsConfiguration); + this.physicsConfiguration = undefined; + } + } /** - * 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. - * + * Load the HTML for the physics config and bind it * @private */ - exports._collapseSector = function() { - // the currently active sector - var sector = this._sector(); + exports._loadPhysicsConfiguration = function () { + if (this.physicsConfiguration === undefined) { + this.backupConstants = {}; + util.deepExtend(this.backupConstants,this.constants); - // 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(); + var maxGravitational = Math.max(20000, (-1 * this.constants.physics.barnesHut.gravitationalConstant) * 10); + var maxSpring = Math.min(0.05, this.constants.physics.barnesHut.springConstant * 10) - // we collapse the sector back to a single cluster - this._collapseThisToSingleCluster(); + 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); - // we move the remaining nodes, edges and nodeIndices to the previous sector. - // This previous sector is the one we will reactivate - this._mergeThisWithFrozen(previousSector); + var 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"); - // 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); + 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; + } - // we activate the previously active (and currently frozen) sector. - this._activateSector(previousSector); + var graph_toggleSmooth = document.getElementById("graph_toggleSmooth"); + var graph_repositionNodes = document.getElementById("graph_repositionNodes"); + var graph_generateOptions = document.getElementById("graph_generateOptions"); - // we load the references from the newly active sector into the global references - this._switchToSector(previousSector); + 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"; + } - // we forget the previously active sector because we reverted to the one before - this._forgetLastSector(); - // finally, we update the node index list. - this._updateNodeIndexList(); + switchConfigurations.apply(this); - // we refresh the list with calulation nodes and calculation node indices. - this._updateCalculationNodes(); - } + radioButton1.onchange = switchConfigurations.bind(this); + radioButton2.onchange = switchConfigurations.bind(this); + radioButton3.onchange = switchConfigurations.bind(this); } }; - /** - * This runs a function in all active sectors. This is used in _redraw() and the _initializeForceCalculation(). + * This overwrites the this.constants. * - * @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 constantsVariableName + * @param value * @private */ - exports._doInAllActiveSectors = function(runFunction,argument) { - var returnValues = []; - 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); - returnValues.push( this[runFunction]() ); - } - } + exports._overWriteGraphConstants = function (constantsVariableName, value) { + var nameArray = constantsVariableName.split("_"); + if (nameArray.length == 1) { + this.constants[nameArray[0]] = value; } - 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) { - returnValues.push( this[runFunction](args[0],args[1]) ); - } - else { - returnValues.push( this[runFunction](argument) ); - } - } - } + 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; } - // we revert the global references back to our active sector - this._loadLatestSector(); - return returnValues; }; /** - * This runs a function in all active sectors. This is used in _redraw() and the _initializeForceCalculation(). + * this function is bound to the toggle smooth curves button. That is also why it is not in the prototype. + */ + function graphToggleSmoothCurves () { + this.constants.smoothCurves.enabled = !this.constants.smoothCurves.enabled; + var graph_toggleSmooth = document.getElementById("graph_toggleSmooth"); + if (this.constants.smoothCurves.enabled == true) {graph_toggleSmooth.style.background = "#A4FF56";} + else {graph_toggleSmooth.style.background = "#FF8532";} + + this._configureSmoothCurves(false); + } + + /** + * this function is used to scramble the nodes * - * @param {String} runFunction | This is the NAME of a function we want to call in all active sectors - * | we dont pass the function itself because then the "this" is the window object - * | instead of the Network object - * @param {*} [argument] | Optional: arguments to pass to the runFunction - * @private */ - exports._doInSupportSector = function(runFunction,argument) { - var returnValues = false; - if (argument === undefined) { - this._switchToSupportSector(); - returnValues = this[runFunction](); + 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._switchToSupportSector(); - var args = Array.prototype.splice.call(arguments, 1); - if (args.length > 1) { - returnValues = this[runFunction](args[0],args[1]); - } - else { - returnValues = this[runFunction](argument); - } + this.repositionNodes(); } - // we revert the global references back to our active sector - this._loadLatestSector(); - return returnValues; - }; - + this.moving = true; + this.start(); + } /** - * 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 + * this is used to generate an options file from the playing with physics system. */ - 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](); + function graphGenerateOptions () { + var options = "No options are required, default values used."; + var optionsSpecific = []; + var radioButton1 = document.getElementById("graph_physicsMethod1"); + var radioButton2 = document.getElementById("graph_physicsMethod2"); + if (radioButton1.checked == true) { + if (this.constants.physics.barnesHut.gravitationalConstant != this.backupConstants.physics.barnesHut.gravitationalConstant) {optionsSpecific.push("gravitationalConstant: " + this.constants.physics.barnesHut.gravitationalConstant);} + if (this.constants.physics.centralGravity != this.backupConstants.physics.barnesHut.centralGravity) {optionsSpecific.push("centralGravity: " + this.constants.physics.centralGravity);} + if (this.constants.physics.springLength != this.backupConstants.physics.barnesHut.springLength) {optionsSpecific.push("springLength: " + this.constants.physics.springLength);} + if (this.constants.physics.springConstant != this.backupConstants.physics.barnesHut.springConstant) {optionsSpecific.push("springConstant: " + this.constants.physics.springConstant);} + if (this.constants.physics.damping != this.backupConstants.physics.barnesHut.damping) {optionsSpecific.push("damping: " + this.constants.physics.damping);} + if (optionsSpecific.length != 0) { + options = "var options = {"; + options += "physics: {barnesHut: {"; + for (var i = 0; i < optionsSpecific.length; i++) { + options += optionsSpecific[i]; + if (i < optionsSpecific.length - 1) { + options += ", " + } + } + options += '}}' + } + if (this.constants.smoothCurves.enabled != this.backupConstants.smoothCurves.enabled) { + if (optionsSpecific.length == 0) {options = "var options = {";} + else {options += ", "} + options += "smoothCurves: " + this.constants.smoothCurves.enabled; + } + if (options != "No options are required, default values used.") { + options += '};' + } + } + else if (radioButton2.checked == true) { + options = "var options = {"; + options += "physics: {barnesHut: {enabled: false}"; + if (this.constants.physics.repulsion.nodeDistance != this.backupConstants.physics.repulsion.nodeDistance) {optionsSpecific.push("nodeDistance: " + this.constants.physics.repulsion.nodeDistance);} + if (this.constants.physics.centralGravity != this.backupConstants.physics.repulsion.centralGravity) {optionsSpecific.push("centralGravity: " + this.constants.physics.centralGravity);} + if (this.constants.physics.springLength != this.backupConstants.physics.repulsion.springLength) {optionsSpecific.push("springLength: " + this.constants.physics.springLength);} + if (this.constants.physics.springConstant != this.backupConstants.physics.repulsion.springConstant) {optionsSpecific.push("springConstant: " + this.constants.physics.springConstant);} + if (this.constants.physics.damping != this.backupConstants.physics.repulsion.damping) {optionsSpecific.push("damping: " + this.constants.physics.damping);} + if (optionsSpecific.length != 0) { + options += ", repulsion: {"; + for (var i = 0; i < optionsSpecific.length; i++) { + options += optionsSpecific[i]; + if (i < optionsSpecific.length - 1) { + options += ", " + } } + options += '}}' + } + if (optionsSpecific.length == 0) {options += "}"} + if (this.constants.smoothCurves != this.backupConstants.smoothCurves) { + options += ", smoothCurves: " + this.constants.smoothCurves; } + options += '};' } else { - 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]); + options = "var options = {"; + if (this.constants.physics.hierarchicalRepulsion.nodeDistance != this.backupConstants.physics.hierarchicalRepulsion.nodeDistance) {optionsSpecific.push("nodeDistance: " + this.constants.physics.hierarchicalRepulsion.nodeDistance);} + if (this.constants.physics.centralGravity != this.backupConstants.physics.hierarchicalRepulsion.centralGravity) {optionsSpecific.push("centralGravity: " + this.constants.physics.centralGravity);} + if (this.constants.physics.springLength != this.backupConstants.physics.hierarchicalRepulsion.springLength) {optionsSpecific.push("springLength: " + this.constants.physics.springLength);} + if (this.constants.physics.springConstant != this.backupConstants.physics.hierarchicalRepulsion.springConstant) {optionsSpecific.push("springConstant: " + this.constants.physics.springConstant);} + if (this.constants.physics.damping != this.backupConstants.physics.hierarchicalRepulsion.damping) {optionsSpecific.push("damping: " + this.constants.physics.damping);} + if (optionsSpecific.length != 0) { + options += "physics: {hierarchicalRepulsion: {"; + for (var i = 0; i < optionsSpecific.length; i++) { + options += optionsSpecific[i]; + if (i < optionsSpecific.length - 1) { + options += ", "; } - else { - this[runFunction](argument); + } + 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 { + options += "enabled:true}"; } + options += '};' } - this._loadLatestSector(); - }; + this.optionsDiv.innerHTML = options; + } + /** - * This runs a function in all sectors. This is used in the _redraw(). + * this is used to switch between barnesHut, repulsion and hierarchical. * - * @param {String} runFunction | This is the NAME of a function we want to call in all active sectors - * | we don't pass the function itself because then the "this" is the window object - * | instead of the Network object - * @param {*} [argument] | Optional: arguments to pass to the runFunction - * @private */ - exports._doInAllSectors = function(runFunction,argument) { - var args = Array.prototype.splice.call(arguments, 1); - if (argument === undefined) { - this._doInAllActiveSectors(runFunction); - this._doInAllFrozenSectors(runFunction); - } - else { - if (args.length > 1) { - this._doInAllActiveSectors(runFunction,args[0],args[1]); - this._doInAllFrozenSectors(runFunction,args[0],args[1]); + function switchConfigurations () { + var ids = ["graph_BH_table", "graph_R_table", "graph_H_table"]; + var radioButton = document.querySelector('input[name="graph_physicsMethod"]:checked').value; + var tableId = "graph_" + radioButton + "_table"; + var table = document.getElementById(tableId); + table.style.display = "block"; + for (var i = 0; i < ids.length; i++) { + if (ids[i] != tableId) { + table = document.getElementById(ids[i]); + table.style.display = "none"; } - else { - this._doInAllActiveSectors(runFunction,argument); - this._doInAllFrozenSectors(runFunction,argument); + } + this._restoreNodes(); + if (radioButton == "R") { + this.constants.hierarchicalLayout.enabled = false; + this.constants.physics.hierarchicalRepulsion.enabled = false; + this.constants.physics.barnesHut.enabled = false; + } + else if (radioButton == "H") { + if (this.constants.hierarchicalLayout.enabled == false) { + this.constants.hierarchicalLayout.enabled = true; + this.constants.physics.hierarchicalRepulsion.enabled = true; + this.constants.physics.barnesHut.enabled = false; + this.constants.smoothCurves.enabled = false; + this._setupHierarchicalLayout(); } } - }; + else { + this.constants.hierarchicalLayout.enabled = false; + this.constants.physics.hierarchicalRepulsion.enabled = false; + this.constants.physics.barnesHut.enabled = true; + } + this._loadSelectedForceSolver(); + var graph_toggleSmooth = document.getElementById("graph_toggleSmooth"); + if (this.constants.smoothCurves.enabled == true) {graph_toggleSmooth.style.background = "#A4FF56";} + else {graph_toggleSmooth.style.background = "#FF8532";} + this.moving = true; + this.start(); + } /** - * 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. + * this generates the ranges depending on the iniital values. * - * @private + * @param id + * @param map + * @param constantsVariableName */ - exports._clearNodeIndexList = function() { - var sector = this._sector(); - this.sectors["active"][sector]["nodeIndices"] = []; - this.nodeIndices = this.sectors["active"][sector]["nodeIndices"]; - }; + function showValueOfRange (id,map,constantsVariableName) { + var valueId = id + "_value"; + var rangeValue = document.getElementById(id).value; + + if (Array.isArray(map)) { + document.getElementById(valueId).value = map[parseInt(rangeValue)]; + this._overWriteGraphConstants(constantsVariableName,map[parseInt(rangeValue)]); + } + else { + document.getElementById(valueId).value = parseInt(map) * parseFloat(rangeValue); + this._overWriteGraphConstants(constantsVariableName, parseInt(map) * parseFloat(rangeValue)); + } + + if (constantsVariableName == "hierarchicalLayout_direction" || + constantsVariableName == "hierarchicalLayout_levelSeparation" || + constantsVariableName == "hierarchicalLayout_nodeSpacing") { + this._setupHierarchicalLayout(); + } + this.moving = true; + this.start(); + } + + +/***/ }, +/* 61 */ +/***/ function(module, exports, __webpack_require__) { + /** - * Draw the encompassing sector node + * Calculate the forces the nodes apply on each other based on a repulsion field. + * This field is linearly approximated. * - * @param ctx - * @param sectorType * @private */ - exports._drawSectorNodes = function(ctx,sectorType) { - var minY = 1e9, maxY = -1e9, minX = 1e9, maxX = -1e9, node; - for (var sector in this.sectors[sectorType]) { - if (this.sectors[sectorType].hasOwnProperty(sector)) { - if (this.sectors[sectorType][sector]["drawingNode"] !== undefined) { + exports._calculateNodeForces = function () { + var dx, dy, angle, distance, fx, fy, combinedClusterSize, + repulsingForce, node1, node2, i, j; - this._switchToSector(sector,sectorType); + var nodes = this.calculationNodes; + var nodeIndices = this.calculationNodeIndices; - 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;} - } + // approximation constants + var a_base = -2 / 3; + var b = 4 / 3; + + // repulsing forces between nodes + var nodeDistance = this.constants.physics.repulsion.nodeDistance; + var minimumDistance = nodeDistance; + + // we loop from i over all but the last entree in the array + // j loops from i+1 to the last. This way we do not double count any of the indices, nor i == j + for (i = 0; i < nodeIndices.length - 1; i++) { + node1 = nodes[nodeIndices[i]]; + for (j = i + 1; j < nodeIndices.length; j++) { + node2 = nodes[nodeIndices[j]]; + combinedClusterSize = node1.clusterSize + node2.clusterSize - 2; + + dx = node2.x - node1.x; + dy = node2.y - node1.y; + distance = Math.sqrt(dx * dx + dy * dy); + + // same condition as BarnesHut, making sure nodes are never 100% overlapping. + if (distance == 0) { + distance = 0.1*Math.random(); + dx = distance; + } + + 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; } - 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.options.radius = Math.sqrt(Math.pow(0.5*node.width,2) + Math.pow(0.5*node.height,2)); - node.setScale(this.scale); - node._drawCircle(ctx); + else { + repulsingForce = a * distance + b; // linear approx of 1 / (1 + Math.exp((distance / minimumDistance - 1) * steepness)) + } + + // amplify the repulsion for clusters. + repulsingForce *= (combinedClusterSize == 0) ? 1 : 1 + combinedClusterSize * this.constants.clustering.forceAmplification; + repulsingForce = repulsingForce / Math.max(distance,0.01*minimumDistance); + + fx = dx * repulsingForce; + fy = dy * repulsingForce; + node1.fx -= fx; + node1.fy -= fy; + node2.fx += fx; + node2.fy += fy; + } } } }; - exports._drawAllSectorNodes = function(ctx) { - this._drawSectorNodes(ctx,"frozen"); - this._drawSectorNodes(ctx,"active"); - this._loadLatestSector(); - }; - /***/ }, /* 62 */ /***/ function(module, exports, __webpack_require__) { - var Node = __webpack_require__(40); - /** - * This function can be called from the _doInAllSectors function + * Calculate the forces the nodes apply on eachother based on a repulsion field. + * This field is linearly approximated. * - * @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); - } - } - } - }; + exports._calculateNodeForces = function () { + var dx, dy, distance, fx, fy, + repulsingForce, node1, node2, i, j; - /** - * 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; - }; + var nodes = this.calculationNodes; + var nodeIndices = this.calculationNodeIndices; + // repulsing forces between nodes + var nodeDistance = this.constants.physics.hierarchicalRepulsion.nodeDistance; - /** - * 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); + // 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]]; - return { - left: x, - top: y, - right: x, - bottom: y - }; - }; + // nodes only affect nodes on their level + if (node1.level == node2.level) { + dx = node2.x - node1.x; + dy = node2.y - node1.y; + distance = Math.sqrt(dx * dx + dy * dy); - /** - * Get the top node at the a specific point (like a click) - * - * @param {{x: Number, y: Number}} pointer - * @return {Node | null} node - * @private - */ - exports._getNodeAt = function (pointer) { - // we first check if this is an navigation controls element - var positionObject = this._pointerToPositionObject(pointer); - var overlappingNodes = this._getAllNodesOverlappingWith(positionObject); - // 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; + 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; + } + } } }; /** - * 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 + * this function calculates the effects of the springs in the case of unsmooth curves. + * * @private */ - exports._getEdgesOverlappingWith = function (object, overlappingEdges) { + exports._calculateHierarchicalSpringForces = function () { + var edgeLength, edge, edgeId; + var dx, dy, fx, fy, springForce, distance; var edges = this.edges; - for (var edgeId in 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; + } + + + // forces caused by the edges, modelled as springs + for (edgeId in edges) { if (edges.hasOwnProperty(edgeId)) { - if (edges[edgeId].isOverlappingWith(object)) { - overlappingEdges.push(edgeId); + edge = edges[edgeId]; + if (edge.connected === true) { + // only calculate forces if nodes are in the same sector + if (this.nodes.hasOwnProperty(edge.toId) && this.nodes.hasOwnProperty(edge.fromId)) { + edgeLength = edge.physics.springLength; + // this implies that the edges between big clusters are longer + edgeLength += (edge.to.clusterSize + edge.from.clusterSize - 2) * this.constants.clustering.edgeGrowth; + + dx = (edge.from.x - edge.to.x); + dy = (edge.from.y - edge.to.y); + distance = Math.sqrt(dx * dx + dy * dy); + + if (distance == 0) { + distance = 0.01; + } + + // the 1/distance is so the fx and fy can be calculated without sine or cosine. + springForce = this.constants.physics.springConstant * (edgeLength - distance) / distance; + + fx = dx * springForce; + fy = dy * springForce; + + + + 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; + } + } } } } - }; - - /** - * 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; - }; + // 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)); - /** - * 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); + node.fx += springFx; + node.fy += springFy; + } - if (overlappingEdges.length > 0) { - return this.edges[overlappingEdges[overlappingEdges.length - 1]]; + // 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; } - else { - return null; + var correctionFx = totalFx / nodeIndices.length; + var correctionFy = totalFy / nodeIndices.length; + + for (i = 0; i < nodeIndices.length; i++) { + var node = nodes[nodeIndices[i]]; + node.fx -= correctionFx; + node.fy -= correctionFy; } + }; +/***/ }, +/* 63 */ +/***/ function(module, exports, __webpack_require__) { /** - * Add object to the selection array. + * 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 obj * @private */ - exports._addToSelection = function(obj) { - if (obj instanceof Node) { - this.selectionObj.nodes[obj.id] = obj; - } - else { - this.selectionObj.edges[obj.id] = obj; - } - }; + exports._calculateNodeForces = function() { + if (this.constants.physics.barnesHut.gravitationalConstant != 0) { + var node; + var nodes = this.calculationNodes; + var nodeIndices = this.calculationNodeIndices; + var nodeCount = nodeIndices.length; - /** - * Add object to the selection array. - * - * @param obj - * @private - */ - exports._addToHover = function(obj) { - if (obj instanceof Node) { - this.hoverObj.nodes[obj.id] = obj; - } - else { - this.hoverObj.edges[obj.id] = obj; + this._formBarnesHutTree(nodes,nodeIndices); + + var barnesHutTree = this.barnesHutTree; + + // place the nodes one by one recursively + for (var i = 0; i < nodeCount; i++) { + node = nodes[nodeIndices[i]]; + if (node.options.mass > 0) { + // starting with root is irrelevant, it never passes the BarnesHut condition + this._getForceContribution(barnesHutTree.root.children.NW,node); + this._getForceContribution(barnesHutTree.root.children.NE,node); + this._getForceContribution(barnesHutTree.root.children.SW,node); + this._getForceContribution(barnesHutTree.root.children.SE,node); + } + } } }; /** - * Remove a single option from selection. + * This function traverses the barnesHutTree. It checks when it can approximate distant nodes with their center of mass. + * If a region contains a single node, we check if it is not itself, then we apply the force. * - * @param {Object} obj + * @param parentBranch + * @param node * @private */ - exports._removeFromSelection = function(obj) { - if (obj instanceof Node) { - delete this.selectionObj.nodes[obj.id]; - } - else { - delete this.selectionObj.edges[obj.id]; + exports._getForceContribution = function(parentBranch,node) { + // we get no force contribution from an empty region + if (parentBranch.childrenCount > 0) { + var dx,dy,distance; + + // get the distance from the center of mass to the node. + dx = parentBranch.centerOfMass.x - node.x; + dy = parentBranch.centerOfMass.y - node.y; + distance = Math.sqrt(dx * dx + dy * dy); + + // BarnesHut condition + // original condition : s/d < thetaInverted = passed === d/s > 1/theta = passed + // calcSize = 1/s --> d * 1/s > 1/theta = passed + if (distance * parentBranch.calcSize > this.constants.physics.barnesHut.thetaInverted) { + // duplicate code to reduce function calls to speed up program + if (distance == 0) { + distance = 0.1*Math.random(); + dx = distance; + } + var gravityForce = this.constants.physics.barnesHut.gravitationalConstant * parentBranch.mass * node.options.mass / (distance * distance * distance); + var fx = dx * gravityForce; + var fy = dy * gravityForce; + node.fx += fx; + node.fy += fy; + } + else { + // Did not pass the condition, go into children if available + if (parentBranch.childrenCount == 4) { + this._getForceContribution(parentBranch.children.NW,node); + this._getForceContribution(parentBranch.children.NE,node); + this._getForceContribution(parentBranch.children.SW,node); + this._getForceContribution(parentBranch.children.SE,node); + } + else { // parentBranch must have only one node, if it was empty we wouldnt be here + if (parentBranch.children.data.id != node.id) { // if it is not self + // duplicate code to reduce function calls to speed up program + if (distance == 0) { + distance = 0.5*Math.random(); + dx = distance; + } + var gravityForce = this.constants.physics.barnesHut.gravitationalConstant * parentBranch.mass * node.options.mass / (distance * distance * distance); + var fx = dx * gravityForce; + var fy = dy * gravityForce; + node.fx += fx; + node.fy += fy; + } + } + } } }; /** - * Unselect all. The selectionObj is useful for this. + * This function constructs the barnesHut tree recursively. It creates the root, splits it and starts placing the nodes. * - * @param {Boolean} [doNotTrigger] | ignore trigger + * @param nodes + * @param nodeIndices * @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(); + 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 (nodes[nodeIndices[i]].options.mass > 0) { + if (x < minX) { minX = x; } + if (x > maxX) { maxX = x; } + if (y < minY) { minY = y; } + if (y > maxY) { maxY = y; } } } + // make the range a square + var sizeDiff = Math.abs(maxX - minX) - Math.abs(maxY - minY); // difference between X and Y + if (sizeDiff > 0) {minY -= 0.5 * sizeDiff; maxY += 0.5 * sizeDiff;} // xSize > ySize + else {minX += 0.5 * sizeDiff; maxX -= 0.5 * sizeDiff;} // xSize < ySize - this.selectionObj = {nodes:{},edges:{}}; - if (doNotTrigger == false) { - this.emit('select', this.getSelection()); - } - }; + 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); - /** - * Unselect all clusters. The selectionObj is useful for this. - * - * @param {Boolean} [doNotTrigger] | ignore trigger - * @private - */ - exports._unselectClusters = function(doNotTrigger) { - if (doNotTrigger === undefined) { - doNotTrigger = false; - } + // 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); - 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]); - } + // place the nodes one by one recursively + for (i = 0; i < nodeCount; i++) { + node = nodes[nodeIndices[i]]; + if (node.options.mass > 0) { + this._placeInTree(barnesHutTree.root,node); } } - if (doNotTrigger == false) { - this.emit('select', this.getSelection()); - } + // make global + this.barnesHutTree = barnesHutTree }; /** - * return the number of selected nodes + * this updates the mass of a branch. this is increased by adding a node. * - * @returns {number} + * @param parentBranch + * @param node * @private */ - exports._getSelectedNodeCount = function() { - var count = 0; - for (var nodeId in this.selectionObj.nodes) { - if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { - count += 1; - } - } - return count; + exports._updateBranchMass = function(parentBranch, node) { + var totalMass = parentBranch.mass + node.options.mass; + var totalMassInv = 1/totalMass; + + parentBranch.centerOfMass.x = parentBranch.centerOfMass.x * parentBranch.mass + node.x * node.options.mass; + parentBranch.centerOfMass.x *= totalMassInv; + + parentBranch.centerOfMass.y = parentBranch.centerOfMass.y * parentBranch.mass + node.y * node.options.mass; + parentBranch.centerOfMass.y *= totalMassInv; + + parentBranch.mass = totalMass; + var biggestSize = Math.max(Math.max(node.height,node.radius),node.width); + parentBranch.maxWidth = (parentBranch.maxWidth < biggestSize) ? biggestSize : parentBranch.maxWidth; + }; + /** - * return the selected node + * determine in which branch the node will be placed. * - * @returns {number} + * @param parentBranch + * @param node + * @param skipMassUpdate * @private */ - exports._getSelectedNode = function() { - for (var nodeId in this.selectionObj.nodes) { - if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { - return this.selectionObj.nodes[nodeId]; - } + exports._placeInTree = function(parentBranch,node,skipMassUpdate) { + if (skipMassUpdate != true || skipMassUpdate === undefined) { + // update the mass of the branch. + this._updateBranchMass(parentBranch,node); } - return null; - }; - /** - * return the selected edge - * - * @returns {number} - * @private - */ - exports._getSelectedEdge = function() { - for (var edgeId in this.selectionObj.edges) { - if (this.selectionObj.edges.hasOwnProperty(edgeId)) { - return this.selectionObj.edges[edgeId]; + if (parentBranch.children.NW.range.maxX > node.x) { // in NW or SW + if (parentBranch.children.NW.range.maxY > node.y) { // in NW + this._placeInRegion(parentBranch,node,"NW"); + } + else { // in SW + this._placeInRegion(parentBranch,node,"SW"); + } + } + else { // in NE or SE + if (parentBranch.children.NW.range.maxY > node.y) { // in NE + this._placeInRegion(parentBranch,node,"NE"); + } + else { // in SE + this._placeInRegion(parentBranch,node,"SE"); } } - return null; }; /** - * return the number of selected edges + * actually place the node in a region (or branch) * - * @returns {number} + * @param parentBranch + * @param node + * @param region * @private */ - exports._getSelectedEdgeCount = function() { - var count = 0; - for (var edgeId in this.selectionObj.edges) { - if (this.selectionObj.edges.hasOwnProperty(edgeId)) { - count += 1; - } + 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; } - return count; }; /** - * return the number of selected objects. + * 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. * - * @returns {number} + * @param parentBranch * @private */ - exports._getSelectedObjectCount = function() { - var count = 0; - for(var nodeId in this.selectionObj.nodes) { - if(this.selectionObj.nodes.hasOwnProperty(nodeId)) { - count += 1; - } + 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; } - for(var edgeId in this.selectionObj.edges) { - if(this.selectionObj.edges.hasOwnProperty(edgeId)) { - count += 1; - } + parentBranch.childrenCount = 4; + parentBranch.children.data = null; + this._insertRegion(parentBranch,"NW"); + this._insertRegion(parentBranch,"NE"); + this._insertRegion(parentBranch,"SW"); + this._insertRegion(parentBranch,"SE"); + + if (containedNode != null) { + this._placeInTree(parentBranch,containedNode); } - return count; }; + /** - * Check if anything is selected + * This function subdivides the region into four new segments. + * Specifically, this inserts a single new segment. + * It fills the children section of the parentBranch * - * @returns {boolean} + * @param parentBranch + * @param region + * @param parentRange * @private */ - exports._selectionIsEmpty = function() { - for(var nodeId in this.selectionObj.nodes) { - if(this.selectionObj.nodes.hasOwnProperty(nodeId)) { - return false; - } - } - for(var edgeId in this.selectionObj.edges) { - if(this.selectionObj.edges.hasOwnProperty(edgeId)) { - return false; - } + 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; } - return true; + + + 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 + }; }; /** - * check if one of the selected nodes is a cluster. + * This function is for debugging purposed, it draws the tree. * - * @returns {boolean} + * @param ctx + * @param color * @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._drawTree = function(ctx,color) { + if (this.barnesHutTree !== undefined) { + + ctx.lineWidth = 1; + + this._drawBranch(this.barnesHutTree.root,ctx,color); } - return false; }; + /** - * select the edges connected to the node that is being selected + * This function is for debugging purposes. It draws the branches recursively. * - * @param {Node} node + * @param branch + * @param ctx + * @param color * @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._drawBranch = function(branch,ctx,color) { + if (color === undefined) { + color = "#FF0000"; } - }; - /** - * select the edges connected to the node that is being selected - * - * @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); + 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(); + ctx.beginPath(); + ctx.moveTo(branch.range.maxX,branch.range.minY); + ctx.lineTo(branch.range.maxX,branch.range.maxY); + ctx.stroke(); - /** - * unselect the edges connected to the node that is being selected - * - * @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); - } + 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(); + } + */ }; +/***/ }, +/* 64 */ +/***/ function(module, exports, __webpack_require__) { + + var Node = __webpack_require__(56); + var Edge = __webpack_require__(57); + var util = __webpack_require__(1); + + exports.startWithClustering = function() { + this.clusteredNodes = {}; + this.moving = true; + this.start(); + } /** - * 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 - * @private + * @param hubsize + * @param options */ - exports._selectObject = function(object, append, doNotTrigger, highlightEdges, overrideSelectable) { - if (doNotTrigger === undefined) { - doNotTrigger = false; + exports.clusterByConnectionCount = function(hubsize, options) { + if (hubsize === undefined) { + hubsize = this._getHubSize(); } - if (highlightEdges === undefined) { - highlightEdges = true; + else if (tyepof(hubsize) == "object") { + options = this._checkOptions(hubsize); + hubsize = this._getHubSize(); } - if (this._selectionIsEmpty() == false && append == false && this.forceAppendSelection == false) { - this._unselectAll(true); + var nodesToCluster = []; + for (var i = 0; i < this.nodeIndices.length; i++) { + var node = this.nodes[this.nodeIndices[i]]; + if (node.edges.length >= hubsize) { + nodesToCluster.push(node.id); + } } - // selectable allows the object to be selected. Override can be used if needed to bypass this. - if (object.selected == false && (this.constants.selectable == true || overrideSelectable)) { - object.select(); - this._addToSelection(object); - if (object instanceof Node && this.blockConnectingEdgeSelection == false && highlightEdges == true) { - this._selectConnectedEdges(object); - } + for (var i = 0; i < nodesToCluster.length; i++) { + var node = this.nodes[nodesToCluster[i]]; + this.clusterByConnection(node,options,{},{},true); } - // do not select the object if selectable is false, only add it to selection to allow drag to work - else if (object.selected == false) { - this._addToSelection(object); - doNotTrigger = true; + this._wrapUp(); + } + + exports.clusterByNodeData = function(options, doNotUpdateCalculationNodes) { + if (options === undefined) { + throw new Error("Cannot call clusterByNodeData without options.") } - else { - object.unselect(); - this._removeFromSelection(object); + if (options.joinCondition === undefined) { + throw new Error("Cannot call clusterByNodeData without a joinCondition function in the options."); } - if (doNotTrigger == false) { - this.emit('select', this.getSelection()); - } - }; + // check if the options object is fine, append if needed + options = this._checkOptions(options); + var childNodesObj = {}; + var childEdgesObj = {} - /** - * This is called when someone clicks on a node. either select or deselect it. - * If there is an existing selection and we don't want to append to it, clear the existing selection - * - * @param {Node || Edge} object - * @private - */ - exports._blurObject = function(object) { - if (object.hover == true) { - object.hover = false; - this.emit("blurNode",{node:object.id}); + // collect the nodes that will be in the cluster + for (var i = 0; i < this.nodeIndices.length; i++) { + var nodeId = this.nodeIndices[i]; + var clonedOptions = this._cloneOptions(nodeId); + if (options.joinCondition(clonedOptions) == true) { + childNodesObj[nodeId] = this.nodes[nodeId]; + } } - }; - /** - * This is called when someone clicks on a node. either select or deselect it. - * If there is an existing selection and we don't want to append to it, clear the existing selection - * - * @param {Node || Edge} object - * @private - */ - exports._hoverObject = function(object) { - if (object.hover == false) { - object.hover = true; - this._addToHover(object); - if (object instanceof Node) { - this.emit("hoverNode",{node:object.id}); + this._cluster(childNodesObj, childEdgesObj, options, doNotUpdateCalculationNodes); + } + + exports.clusterOutliers = function(options, doNotUpdateCalculationNodes) { + options = this._checkOptions(options); + + var clusters = [] + + // collect the nodes that will be in the cluster + for (var i = 0; i < this.nodeIndices.length; i++) { + var childNodesObj = {}; + var childEdgesObj = {}; + var nodeId = this.nodeIndices[i]; + if (this.nodes[nodeId].edges.length == 1) { + var edge = this.nodes[nodeId].edges[0]; + var childNodeId = this._getConnectedId(edge, nodeId); + if (childNodeId != nodeId) { + if (options.joinCondition === undefined) { + childNodesObj[nodeId] = this.nodes[nodeId]; + childNodesObj[childNodeId] = this.nodes[childNodeId]; + } + else { + var clonedOptions = this._cloneOptions(nodeId); + if (options.joinCondition(clonedOptions) == true) { + childNodesObj[nodeId] = this.nodes[nodeId]; + } + clonedOptions = this._cloneOptions(childNodeId); + if (options.joinCondition(clonedOptions) == true) { + childNodesObj[childNodeId] = this.nodes[childNodeId]; + } + } + clusters.push({nodes:childNodesObj, edges:childEdgesObj}) + } } } - if (object instanceof Node) { - this._hoverConnectedEdges(object); + + for (var i = 0; i < clusters.length; i++) { + this._cluster(clusters[i].nodes, clusters[i].edges, options, true) } - }; + this._wrapUp(); - /** - * 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._handleTouch = function(pointer) { - }; + } /** - * handles the selection part of the tap; * - * @param {Object} pointer - * @private - */ - exports._handleTap = function(pointer) { - var node = this._getNodeAt(pointer); - if (node != null) { - this._selectObject(node, false); - } - else { - var edge = this._getEdgeAt(pointer); - if (edge != null) { - this._selectObject(edge, false); + * @param nodeId + * @param options + * @param doNotUpdateCalculationNodes + */ + exports.clusterByConnection = function(nodeId, options, doNotUpdateCalculationNodes) { + // kill conditions + if (nodeId === undefined) {throw new Error("No nodeId supplied to clusterByConnection!");} + if (this.nodes[nodeId] === undefined) {throw new Error("The nodeId given to clusterByConnection does not exist!");} + + var node = this.nodes[nodeId]; + options = this._checkOptions(options, node); + if (options.clusterNodeProperties.x === undefined) {options.clusterNodeProperties.x = node.x; options.clusterNodeProperties.allowedToMoveX = !node.xFixed;} + if (options.clusterNodeProperties.y === undefined) {options.clusterNodeProperties.y = node.y; options.clusterNodeProperties.allowedToMoveY = !node.yFixed;} + + var childNodesObj = {}; + var edge; + var childEdgesObj = {} + var childNodeId; + var parentNodeId = node.id; + var parentClonedOptions = this._cloneOptions(parentNodeId); + childNodesObj[parentNodeId] = node; + + // collect the nodes that will be in the cluster + for (var i = 0; i < node.edges.length; i++) { + edge = node.edges[i]; + childNodeId = this._getConnectedId(edge, parentNodeId); + + if (childNodeId !== parentNodeId) { + if (options.joinCondition === undefined) { + childEdgesObj[edge.id] = edge; + childNodesObj[childNodeId] = this.nodes[childNodeId]; + } + else { + // clone the options and insert some additional parameters that could be interesting. + var childClonedOptions = this._cloneOptions(childNodeId); + if (options.joinCondition(parentClonedOptions, childClonedOptions) == true) { + childEdgesObj[edge.id] = edge; + childNodesObj[childNodeId] = this.nodes[childNodeId]; + } + } } else { - this._unselectAll(); + childEdgesObj[edge.id] = edge; } } - var properties = this.getSelection(); - properties['pointer'] = { - DOM: {x: pointer.x, y: pointer.y}, - canvas: {x: this._XconvertDOMtoCanvas(pointer.x), y: this._YconvertDOMtoCanvas(pointer.y)} + + this._cluster(childNodesObj, childEdgesObj, options, doNotUpdateCalculationNodes); + } + + exports._cloneOptions = function(objId, type) { + var clonedOptions = {}; + if (type === undefined || type == 'node') { + util.deepExtend(clonedOptions, this.nodes[objId].options, true); + util.deepExtend(clonedOptions, this.nodes[objId].properties, true); + clonedOptions.amountOfConnections = this.nodes[objId].edges.length; } - this.emit("click", properties); - this._requestRedraw(); - }; + else { + util.deepExtend(clonedOptions, this.edges[objId].options, true); + util.deepExtend(clonedOptions, this.edges[objId].properties, true); + } + return clonedOptions; + } + + exports._createClusterEdges = function (childNodesObj, childEdgesObj, newEdges, options) { + var edge, childNodeId, childNode; + + var childKeys = Object.keys(childNodesObj); + for (var i = 0; i < childKeys.length; i++) { + childNodeId = childKeys[i]; + childNode = childNodesObj[childNodeId]; + + // mark all edges for removal from global and construct new edges from the cluster to others + for (var j = 0; j < childNode.edges.length; j++) { + edge = childNode.edges[j]; + childEdgesObj[edge.id] = edge; + + var otherNodeId = edge.toId; + var otherOnTo = true; + if (edge.toId != childNodeId) { + otherNodeId = edge.toId; + otherOnTo = true; + } + else if (edge.fromId != childNodeId) { + otherNodeId = edge.fromId; + otherOnTo = false; + } + + if (childNodesObj[otherNodeId] === undefined) { + var clonedOptions = this._cloneOptions(edge.id, 'edge'); + util.deepExtend(clonedOptions, options.clusterEdgeProperties); + // avoid forcing the default color on edges that inherit color + if (edge.properties.color === undefined) { + delete clonedOptions.color; + } + + if (otherOnTo === true) { + clonedOptions.from = options.clusterNodeProperties.id; + clonedOptions.to = otherNodeId; + } + else { + clonedOptions.from = otherNodeId; + clonedOptions.to = options.clusterNodeProperties.id; + } + clonedOptions.id = 'clusterEdge:' + util.randomUUID(); + newEdges.push(new Edge(clonedOptions,this,this.constants)) + } + } + } + } + exports._checkOptions = function(options) { + if (options === undefined) {options = {};} + if (options.clusterEdgeProperties === undefined) {options.clusterEdgeProperties = {};} + if (options.clusterNodeProperties === undefined) {options.clusterNodeProperties = {};} + + + return options; + } + /** - * handles the selection part of the double tap and opens a cluster if needed * - * @param {Object} pointer + * @param {Object} childNodesObj | object with node objects, id as keys, same as childNodes except it also contains a source node + * @param {Object} childEdgesObj | object with edge objects, id as keys + * @param {Array} options | object with {clusterNodeProperties, clusterEdgeProperties, processProperties} + * @param {Boolean} doNotUpdateCalculationNodes | when true, do not wrap up * @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._cluster = function(childNodesObj, childEdgesObj, options, doNotUpdateCalculationNodes) { + // kill condition: no children so cant cluster + if (Object.keys(childNodesObj).length == 0) {return;} + + // check if we have an unique id; + if (options.clusterNodeProperties.id === undefined) {options.clusterNodeProperties.id = 'cluster:' + util.randomUUID();} + var clusterId = options.clusterNodeProperties.id; + + // create the new edges that will connect to the cluster + var newEdges = []; + this._createClusterEdges(childNodesObj, childEdgesObj, newEdges, options); + + // construct the clusterNodeProperties + var clusterNodeProperties = options.clusterNodeProperties; + if (options.processProperties !== undefined) { + // get the childNode options + var childNodesOptions = []; + for (var nodeId in childNodesObj) { + var clonedOptions = this._cloneOptions(nodeId); + childNodesOptions.push(clonedOptions); + } + + // get clusterproperties based on childNodes + var childEdgesOptions = []; + for (var edgeId in childEdgesObj) { + var clonedOptions = this._cloneOptions(edgeId, 'edge'); + childEdgesOptions.push(clonedOptions); + } + + clusterNodeProperties = options.processProperties(clusterNodeProperties, childNodesOptions, childEdgesOptions); + if (!clusterNodeProperties) { + throw new Error("The processClusterProperties function does not return properties!"); + } } - var properties = this.getSelection(); - properties['pointer'] = { - DOM: {x: pointer.x, y: pointer.y}, - canvas: {x: this._XconvertDOMtoCanvas(pointer.x), y: this._YconvertDOMtoCanvas(pointer.y)} + if (clusterNodeProperties.label === undefined) { + clusterNodeProperties.label = 'cluster'; } - this.emit("doubleClick", properties); - }; - /** - * Handle the onHold selection part - * - * @param pointer - * @private - */ - exports._handleOnHold = function(pointer) { - var node = this._getNodeAt(pointer); - if (node != null) { - this._selectObject(node,true); + // give the clusterNode a postion if it does not have one. + var pos = undefined + if (clusterNodeProperties.x === undefined) { + pos = this._getClusterPosition(childNodesObj); + clusterNodeProperties.x = pos.x; + clusterNodeProperties.allowedToMoveX = true; } - else { - var edge = this._getEdgeAt(pointer); - if (edge != null) { - this._selectObject(edge,true); + if (clusterNodeProperties.x === undefined) { + if (pos === undefined) { + pos = this._getClusterPosition(childNodesObj); } + clusterNodeProperties.y = pos.y; + clusterNodeProperties.allowedToMoveY = true; } - this._requestRedraw(); - }; - /** - * handle the onRelease event. These functions are here for the navigation controls module - * and data manipulation module. - * - * @private - */ - exports._handleOnRelease = function(pointer) { - this._manipulationReleaseOverload(pointer); - this._navigationReleaseOverload(pointer); - }; + // force the ID to remain the same + clusterNodeProperties.id = clusterId; + + + // create the clusterNode + var clusterNode = new Node(clusterNodeProperties, this.images, this.groups, this.constants); + clusterNode.containedNodes = childNodesObj; + clusterNode.containedEdges = childEdgesObj; + + + // delete contained edges from global + for (var edgeId in childEdgesObj) { + if (childEdgesObj.hasOwnProperty(edgeId)) { + if (this.edges[edgeId] !== undefined) { + if (this.edges[edgeId].via !== null) { + var viaId = this.edges[edgeId].via.id; + if (viaId) { + this.edges[edgeId].via = null + delete this.sectors['support']['nodes'][viaId]; + } + } + this.edges[edgeId].disconnect(); + delete this.edges[edgeId]; + } + } + } + + + // remove contained nodes from global + for (var nodeId in childNodesObj) { + if (childNodesObj.hasOwnProperty(nodeId)) { + this.clusteredNodes[nodeId] = {clusterId:clusterNodeProperties.id, node: this.nodes[nodeId]}; + delete this.nodes[nodeId]; + } + } + + + // finally put the cluster node into global + this.nodes[clusterNodeProperties.id] = clusterNode; + + + // push new edges to global + for (var i = 0; i < newEdges.length; i++) { + this.edges[newEdges[i].id] = newEdges[i]; + this.edges[newEdges[i].id].connect(); + } + + + // create bezier nodes for smooth curves if needed + this._createBezierNodes(newEdges); + + + // set ID to undefined so no duplicates arise + clusterNodeProperties.id = undefined; + + + // wrap up + if (doNotUpdateCalculationNodes !== true) { + this._wrapUp(); + } + } - exports._manipulationReleaseOverload = function (pointer) {}; - exports._navigationReleaseOverload = function (pointer) {}; /** - * - * retrieve the currently selected objects - * @return {{nodes: Array., edges: Array.}} selection + * get the position of the cluster node based on what's inside + * @param {object} childNodesObj | object with node objects, id as keys + * @returns {{x: number, y: number}} + * @private */ - exports.getSelection = function() { - var nodeIds = this.getSelectedNodes(); - var edgeIds = this.getSelectedEdges(); - return {nodes:nodeIds, edges:edgeIds}; - }; + exports._getClusterPosition = function(childNodesObj) { + var childKeys = Object.keys(childNodesObj); + var minX = childNodesObj[childKeys[0]].x; + var maxX = childNodesObj[childKeys[0]].x; + var minY = childNodesObj[childKeys[0]].y; + var maxY = childNodesObj[childKeys[0]].y; + var node; + for (var i = 0; i < childKeys.lenght; i++) { + node = childNodesObj[childKeys[0]]; + minX = node.x < minX ? node.x : minX; + maxX = node.x > maxX ? node.x : maxX; + minY = node.y < minY ? node.y : minY; + maxY = node.y > maxY ? node.y : maxY; + } + return {x: 0.5*(minX + maxX), y: 0.5*(minY + maxY)}; + } + /** - * - * retrieve the currently selected nodes - * @return {String[]} selection An array with the ids of the - * selected nodes. + * Open a cluster by calling this function. + * @param {String} clusterNodeId | the ID of the cluster node + * @param {Boolean} doNotUpdateCalculationNodes | wrap up afterwards if not true */ - exports.getSelectedNodes = function() { - var idArray = []; - if (this.constants.selectable == true) { - for (var nodeId in this.selectionObj.nodes) { - if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { - idArray.push(nodeId); + exports.openCluster = function(clusterNodeId, doNotUpdateCalculationNodes) { + // kill conditions + if (clusterNodeId === undefined) {throw new Error("No clusterNodeId supplied to openCluster.");} + if (this.nodes[clusterNodeId] === undefined) {throw new Error("The clusterNodeId supplied to openCluster does not exist.");} + if (this.nodes[clusterNodeId].containedNodes === undefined) {console.log("The node:" + clusterNodeId + " is not a cluster."); return}; + + var node = this.nodes[clusterNodeId]; + var containedNodes = node.containedNodes; + var containedEdges = node.containedEdges; + + // release nodes + for (var nodeId in containedNodes) { + if (containedNodes.hasOwnProperty(nodeId)) { + this.nodes[nodeId] = containedNodes[nodeId]; + // inherit position + this.nodes[nodeId].x = node.x; + this.nodes[nodeId].y = node.y; + + // inherit speed + this.nodes[nodeId].vx = node.vx; + this.nodes[nodeId].vy = node.vy; + + delete this.clusteredNodes[nodeId]; + } + } + + // release edges + for (var edgeId in containedEdges) { + if (containedEdges.hasOwnProperty(edgeId)) { + this.edges[edgeId] = containedEdges[edgeId]; + this.edges[edgeId].connect(); + var edge = this.edges[edgeId]; + if (edge.connected === false) { + if (this.clusteredNodes[edge.fromId] !== undefined) { + this._connectEdge(edge, edge.fromId, true); + } + if (this.clusteredNodes[edge.toId] !== undefined) { + this._connectEdge(edge, edge.toId, false); + } } } } - return idArray - }; + this._createBezierNodes(containedEdges); - /** - * - * retrieve the currently selected edges - * @return {Array} selection An array with the ids of the - * selected nodes. - */ - exports.getSelectedEdges = function() { - var idArray = []; - if (this.constants.selectable == true) { - for (var edgeId in this.selectionObj.edges) { - if (this.selectionObj.edges.hasOwnProperty(edgeId)) { - idArray.push(edgeId); + var edgeIds = []; + for (var i = 0; i < node.edges.length; i++) { + edgeIds.push(node.edges[i].id); + } + + // remove edges in clusterNode + for (var i = 0; i < edgeIds.length; i++) { + var edge = this.edges[edgeIds[i]]; + // if the edge should have been connected to a contained node + if (edge.fromArray.length > 0 && edge.fromId == clusterNodeId) { + // the node in the from array was contained in the cluster + if (this.nodes[edge.fromArray[0].id] !== undefined) { + this._connectEdge(edge, edge.fromArray[0].id, true); + } + } + else if (edge.toArray.length > 0 && edge.toId == clusterNodeId) { + // the node in the to array was contained in the cluster + if (this.nodes[edge.toArray[0].id] !== undefined) { + this._connectEdge(edge, edge.toArray[0].id, false); } } + else { + var edgeId = edgeIds[i]; + var viaId = this.edges[edgeId].via.id; + if (viaId) { + this.edges[edgeId].via = null + delete this.sectors['support']['nodes'][viaId]; + } + // this removes the edge from node.edges, which is why edgeIds is formed + this.edges[edgeId].disconnect(); + delete this.edges[edgeId]; + } } - return idArray; - }; + // remove clusterNode + delete this.nodes[clusterNodeId]; - /** - * select zero or more nodes DEPRICATED - * @param {Number[] | String[]} selection An array with the ids of the - * selected nodes. - */ - exports.setSelection = function() { - console.log("setSelection is deprecated. Please use selectNodes instead.") - }; + if (doNotUpdateCalculationNodes !== true) { + this._wrapUp(); + } + } + + exports._wrapUp = function() { + this._updateNodeIndexList(); + this._updateCalculationNodes(); + this._markAllEdgesAsDirty(); + this.moving = true; + this.start(); + } + + exports._connectEdge = function(edge, nodeId, from) { + var clusterStack = this._getClusterStack(nodeId); + if (from == true) { + edge.from = clusterStack[clusterStack.length - 1]; + edge.fromId = clusterStack[clusterStack.length - 1].id; + clusterStack.pop() + edge.fromArray = clusterStack; + } + else { + edge.to = clusterStack[clusterStack.length - 1]; + edge.toId = clusterStack[clusterStack.length - 1].id; + clusterStack.pop(); + edge.toArray = clusterStack; + } + edge.connect(); + } + exports._getClusterStack = function(nodeId) { + var stack = []; + var max = 100; + var counter = 0; + + while (this.clusteredNodes[nodeId] !== undefined && counter < max) { + stack.push(this.clusteredNodes[nodeId].node); + nodeId = this.clusteredNodes[nodeId].clusterId; + counter++; + } + stack.push(this.nodes[nodeId]); + return stack; + } + + + exports._getConnectedId = function(edge, nodeId) { + if (edge.toId != nodeId) { + return edge.toId; + } + else if (edge.fromId != nodeId) { + return edge.fromId; + } + else { + return edge.fromId; + } + } /** - * 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] + * 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.selectNodes = function(selection, highlightEdges) { - var i, iMax, id; + exports._getHubSize = function() { + var average = 0; + var averageSquared = 0; + var hubCounter = 0; + var largestHub = 0; - if (!selection || (selection.length == undefined)) - throw 'Selection must be an array with ids'; + for (var i = 0; i < this.nodeIndices.length; i++) { + var node = this.nodes[this.nodeIndices[i]]; + if (node.edges.length > largestHub) { + largestHub = node.edges.length; + } + average += node.edges.length; + averageSquared += Math.pow(node.edges.length,2); + hubCounter += 1; + } + average = average / hubCounter; + averageSquared = averageSquared / hubCounter; - // first unselect any selected node - this._unselectAll(true); + var variance = averageSquared - Math.pow(average,2); + var standardDeviation = Math.sqrt(variance); - for (i = 0, iMax = selection.length; i < iMax; i++) { - id = selection[i]; + var hubThreshold = Math.floor(average + 2*standardDeviation); - var node = this.nodes[id]; - if (!node) { - throw new RangeError('Node with id "' + id + '" not found'); - } - this._selectObject(node,true,true,highlightEdges,true); + // always have at least one to cluster + if (hubThreshold > largestHub) { + hubThreshold = largestHub; } - this.redraw(); + + return hubThreshold; }; + +/***/ }, +/* 65 */ +/***/ function(module, exports, __webpack_require__) { + + var util = __webpack_require__(1); + var Node = __webpack_require__(56); + /** - * select zero or more edges - * @param {Number[] | String[]} selection An array with the ids of the - * selected nodes. + * Creation of the SectorMixin var. + * + * This contains all the functions the Network object can use to employ the sector system. + * The sector system is always used by Network, though the benefits only apply to the use of clustering. + * If clustering is not used, there is no overhead except for a duplicate object with references to nodes and edges. */ - exports.selectEdges = function(selection) { - var i, iMax, id; - - if (!selection || (selection.length == undefined)) - throw 'Selection must be an array with ids'; - // first unselect any selected node - this._unselectAll(true); + /** + * 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. + * + * @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; + }; - 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,false,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); + } + else { + this._switchToFrozenSector(sectorId); } - this.redraw(); }; + /** - * Validate the selection: remove ids of nodes which no longer exist + * This function sets the global references to nodes, edges and nodeIndices back to + * those of the supplied active sector. + * + * @param sectorId * @private */ - exports._updateSelection = function () { - for(var nodeId in this.selectionObj.nodes) { - if(this.selectionObj.nodes.hasOwnProperty(nodeId)) { - if (!this.nodes.hasOwnProperty(nodeId)) { - delete this.selectionObj.nodes[nodeId]; - } - } - } - for(var edgeId in this.selectionObj.edges) { - if(this.selectionObj.edges.hasOwnProperty(edgeId)) { - if (!this.edges.hasOwnProperty(edgeId)) { - delete this.selectionObj.edges[edgeId]; - } - } - } + 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"]; }; -/***/ }, -/* 63 */ -/***/ function(module, exports, __webpack_require__) { + /** + * This function sets the global references to nodes, edges and nodeIndices back to + * those of the supplied active sector. + * + * @private + */ + exports._switchToSupportSector = function() { + this.nodeIndices = this.sectors["support"]["nodeIndices"]; + this.nodes = this.sectors["support"]["nodes"]; + this.edges = this.sectors["support"]["edges"]; + }; - var util = __webpack_require__(1); - var Node = __webpack_require__(40); - var Edge = __webpack_require__(37); /** - * clears the toolbar div element of children + * This function sets the global references to nodes, edges and nodeIndices back to + * those of the supplied frozen sector. * + * @param sectorId * @private */ - exports._clearManipulatorBar = function() { - this._recursiveDOMDelete(this.manipulationDiv); - this.manipulationDOM = {}; + 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._manipulationReleaseOverload = function () {}; - delete this.sectors['support']['nodes']['targetNode']; - delete this.sectors['support']['nodes']['targetViaNode']; - this.controlNodesActive = false; - this.freezeSimulationEnabled = false; + + /** + * This function sets the global references to nodes, edges and nodeIndices back to + * those of the currently active sector. + * + * @private + */ + exports._loadLatestSector = function() { + this._switchToSector(this._sector()); }; + /** - * 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 function returns the currently active sector Id * + * @returns {String} * @private */ - exports._restoreOverloadedFunctions = function() { - for (var functionName in this.cachedFunctions) { - if (this.cachedFunctions.hasOwnProperty(functionName)) { - this[functionName] = this.cachedFunctions[functionName]; - delete this.cachedFunctions[functionName]; - } - } + exports._sector = function() { + return this.activeSector[this.activeSector.length-1]; }; + /** - * Enable or disable edit-mode. + * This function returns the previously active sector Id * + * @returns {String} * @private */ - exports._toggleEditMode = function() { - this.editMode = !this.editMode; - var toolbar = this.manipulationDiv; - var closeDiv = this.closeDiv; - var editModeDiv = this.editModeDiv; - if (this.editMode == true) { - toolbar.style.display="block"; - closeDiv.style.display="block"; - editModeDiv.style.display="none"; - closeDiv.onclick = this._toggleEditMode.bind(this); + exports._previousSector = function() { + if (this.activeSector.length > 1) { + return this.activeSector[this.activeSector.length-2]; } else { - toolbar.style.display="none"; - closeDiv.style.display="none"; - editModeDiv.style.display="block"; - closeDiv.onclick = null; + throw new TypeError('there are not enough sectors in the this.activeSector array.'); } - this._createManipulatorBar() }; + /** - * main function, creates the main toolbar. Removes functions bound to the select event. Binds all the buttons of the toolbar. + * We add the active sector at the end of the this.activeSector array + * This ensures it is the currently active sector returned by _sector() and it reaches the top + * of the activeSector stack. When we reverse our steps we move from the end to the beginning of this stack. * + * @param newId * @private */ - exports._createManipulatorBar = function() { - // remove bound functions - if (this.boundFunction) { - this.off('select', this.boundFunction); - } + exports._setActiveSector = function(newId) { + this.activeSector.push(newId); + }; - var locale = this.constants.locales[this.constants.locale]; - if (this.edgeBeingEdited !== undefined) { - this.edgeBeingEdited._disableControlNodes(); - this.edgeBeingEdited = undefined; - this.selectedControlNode = null; - this.controlNodesActive = false; - this._redraw(); - } + /** + * We remove the currently active sector id from the active sector stack. This happens when + * we reactivate the previously active sector + * + * @private + */ + exports._forgetLastSector = function() { + this.activeSector.pop(); + }; - // restore overloaded functions - this._restoreOverloadedFunctions(); - // resume calculation - this.freezeSimulationEnabled = false; + /** + * 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}; - // reset global variables - this.blockConnectingEdgeSelection = false; - this.forceAppendSelection = false; - this.manipulationDOM = {}; + // create the new sector render node. This gives visual feedback that you are in a new sector. + this.sectors["active"][newId]['drawingNode'] = new Node( + {id:newId, + color: { + background: "#eaefef", + border: "495c5e" + } + },{},{},this.constants); + this.sectors["active"][newId]['drawingNode'].clusterSize = 2; + }; - if (this.editMode == true) { - while (this.manipulationDiv.hasChildNodes()) { - this.manipulationDiv.removeChild(this.manipulationDiv.firstChild); - } - this.manipulationDOM['addNodeSpan'] = document.createElement('span'); - this.manipulationDOM['addNodeSpan'].className = 'network-manipulationUI add'; - this.manipulationDOM['addNodeLabelSpan'] = document.createElement('span'); - this.manipulationDOM['addNodeLabelSpan'].className = 'network-manipulationLabel'; - this.manipulationDOM['addNodeLabelSpan'].innerHTML = locale['addNode']; - this.manipulationDOM['addNodeSpan'].appendChild(this.manipulationDOM['addNodeLabelSpan']); + /** + * 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.manipulationDOM['seperatorLineDiv1'] = document.createElement('div'); - this.manipulationDOM['seperatorLineDiv1'].className = 'network-seperatorLine'; - this.manipulationDOM['addEdgeSpan'] = document.createElement('span'); - this.manipulationDOM['addEdgeSpan'].className = 'network-manipulationUI connect'; - this.manipulationDOM['addEdgeLabelSpan'] = document.createElement('span'); - this.manipulationDOM['addEdgeLabelSpan'].className = 'network-manipulationLabel'; - this.manipulationDOM['addEdgeLabelSpan'].innerHTML = locale['addEdge']; - this.manipulationDOM['addEdgeSpan'].appendChild(this.manipulationDOM['addEdgeLabelSpan']); + /** + * 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.manipulationDiv.appendChild(this.manipulationDOM['addNodeSpan']); - this.manipulationDiv.appendChild(this.manipulationDOM['seperatorLineDiv1']); - this.manipulationDiv.appendChild(this.manipulationDOM['addEdgeSpan']); - if (this._getSelectedNodeCount() == 1 && this.triggerFunctions.edit) { - this.manipulationDOM['seperatorLineDiv2'] = document.createElement('div'); - this.manipulationDOM['seperatorLineDiv2'].className = 'network-seperatorLine'; + /** + * 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 sectorId + * @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]; - this.manipulationDOM['editNodeSpan'] = document.createElement('span'); - this.manipulationDOM['editNodeSpan'].className = 'network-manipulationUI edit'; - this.manipulationDOM['editNodeLabelSpan'] = document.createElement('span'); - this.manipulationDOM['editNodeLabelSpan'].className = 'network-manipulationLabel'; - this.manipulationDOM['editNodeLabelSpan'].innerHTML = locale['editNode']; - this.manipulationDOM['editNodeSpan'].appendChild(this.manipulationDOM['editNodeLabelSpan']); + // we have moved the sector data into the frozen set, we now remove it from the active set + this._deleteActiveSector(sectorId); + }; - this.manipulationDiv.appendChild(this.manipulationDOM['seperatorLineDiv2']); - this.manipulationDiv.appendChild(this.manipulationDOM['editNodeSpan']); - } - else if (this._getSelectedEdgeCount() == 1 && this._getSelectedNodeCount() == 0) { - this.manipulationDOM['seperatorLineDiv3'] = document.createElement('div'); - this.manipulationDOM['seperatorLineDiv3'].className = 'network-seperatorLine'; - this.manipulationDOM['editEdgeSpan'] = document.createElement('span'); - this.manipulationDOM['editEdgeSpan'].className = 'network-manipulationUI edit'; - this.manipulationDOM['editEdgeLabelSpan'] = document.createElement('span'); - this.manipulationDOM['editEdgeLabelSpan'].className = 'network-manipulationLabel'; - this.manipulationDOM['editEdgeLabelSpan'].innerHTML = locale['editEdge']; - this.manipulationDOM['editEdgeSpan'].appendChild(this.manipulationDOM['editEdgeLabelSpan']); + /** + * 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]; - this.manipulationDiv.appendChild(this.manipulationDOM['seperatorLineDiv3']); - this.manipulationDiv.appendChild(this.manipulationDOM['editEdgeSpan']); - } - if (this._selectionIsEmpty() == false) { - this.manipulationDOM['seperatorLineDiv4'] = document.createElement('div'); - this.manipulationDOM['seperatorLineDiv4'].className = 'network-seperatorLine'; + // we have moved the sector data into the active set, we now remove it from the frozen stack + this._deleteFrozenSector(sectorId); + }; - this.manipulationDOM['deleteSpan'] = document.createElement('span'); - this.manipulationDOM['deleteSpan'].className = 'network-manipulationUI delete'; - this.manipulationDOM['deleteLabelSpan'] = document.createElement('span'); - this.manipulationDOM['deleteLabelSpan'].className = 'network-manipulationLabel'; - this.manipulationDOM['deleteLabelSpan'].innerHTML = locale['del']; - this.manipulationDOM['deleteSpan'].appendChild(this.manipulationDOM['deleteLabelSpan']); - this.manipulationDiv.appendChild(this.manipulationDOM['seperatorLineDiv4']); - this.manipulationDiv.appendChild(this.manipulationDOM['deleteSpan']); + /** + * 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]; } + } - - // bind the icons - this.manipulationDOM['addNodeSpan'].onclick = this._createAddNodeToolbar.bind(this); - this.manipulationDOM['addEdgeSpan'].onclick = this._createAddEdgeToolbar.bind(this); - if (this._getSelectedNodeCount() == 1 && this.triggerFunctions.edit) { - this.manipulationDOM['editNodeSpan'].onclick = this._editNode.bind(this); - } - else if (this._getSelectedEdgeCount() == 1 && this._getSelectedNodeCount() == 0) { - this.manipulationDOM['editEdgeSpan'].onclick = this._createEditEdgeToolbar.bind(this); - } - if (this._selectionIsEmpty() == false) { - this.manipulationDOM['deleteSpan'].onclick = this._deleteSelected.bind(this); + // 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]; } - this.closeDiv.onclick = this._toggleEditMode.bind(this); - - var me = this; - this.boundFunction = me._createManipulatorBar; - this.on('select', this.boundFunction); } - else { - while (this.editModeDiv.hasChildNodes()) { - this.editModeDiv.removeChild(this.editModeDiv.firstChild); - } - - this.manipulationDOM['editModeSpan'] = document.createElement('span'); - this.manipulationDOM['editModeSpan'].className = 'network-manipulationUI edit editmode'; - this.manipulationDOM['editModeLabelSpan'] = document.createElement('span'); - this.manipulationDOM['editModeLabelSpan'].className = 'network-manipulationLabel'; - this.manipulationDOM['editModeLabelSpan'].innerHTML = locale['edit']; - this.manipulationDOM['editModeSpan'].appendChild(this.manipulationDOM['editModeLabelSpan']); - - this.editModeDiv.appendChild(this.manipulationDOM['editModeSpan']); - this.manipulationDOM['editModeSpan'].onclick = this._toggleEditMode.bind(this); + // merge the nodeIndices + for (var i = 0; i < this.nodeIndices.length; i++) { + this.sectors["frozen"][sectorId]["nodeIndices"].push(this.nodeIndices[i]); } }; - /** - * Create the toolbar for adding Nodes + * 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._createAddNodeToolbar = function() { - // clear the toolbar - this._clearManipulatorBar(); - if (this.boundFunction) { - this.off('select', this.boundFunction); - } - - var locale = this.constants.locales[this.constants.locale]; - - this.manipulationDOM = {}; - this.manipulationDOM['backSpan'] = document.createElement('span'); - this.manipulationDOM['backSpan'].className = 'network-manipulationUI back'; - this.manipulationDOM['backLabelSpan'] = document.createElement('span'); - this.manipulationDOM['backLabelSpan'].className = 'network-manipulationLabel'; - this.manipulationDOM['backLabelSpan'].innerHTML = locale['back']; - this.manipulationDOM['backSpan'].appendChild(this.manipulationDOM['backLabelSpan']); - - this.manipulationDOM['seperatorLineDiv1'] = document.createElement('div'); - this.manipulationDOM['seperatorLineDiv1'].className = 'network-seperatorLine'; - - this.manipulationDOM['descriptionSpan'] = document.createElement('span'); - this.manipulationDOM['descriptionSpan'].className = 'network-manipulationUI none'; - this.manipulationDOM['descriptionLabelSpan'] = document.createElement('span'); - this.manipulationDOM['descriptionLabelSpan'].className = 'network-manipulationLabel'; - this.manipulationDOM['descriptionLabelSpan'].innerHTML = locale['addDescription']; - this.manipulationDOM['descriptionSpan'].appendChild(this.manipulationDOM['descriptionLabelSpan']); - - this.manipulationDiv.appendChild(this.manipulationDOM['backSpan']); - this.manipulationDiv.appendChild(this.manipulationDOM['seperatorLineDiv1']); - this.manipulationDiv.appendChild(this.manipulationDOM['descriptionSpan']); - - // bind the icon - this.manipulationDOM['backSpan'].onclick = this._createManipulatorBar.bind(this); - - // we use the boundFunction so we can reference it when we unbind it from the "select" event. - var me = this; - this.boundFunction = me._addNode; - this.on('select', this.boundFunction); + exports._collapseThisToSingleCluster = function() { + this.clusterToFit(1,false); }; /** - * create the toolbar to connect nodes + * We create a new active sector from the node that we want to open. * + * @param node * @private */ - exports._createAddEdgeToolbar = function() { - // clear the toolbar - this._clearManipulatorBar(); - this._unselectAll(true); - this.freezeSimulationEnabled = true; - - if (this.boundFunction) { - this.off('select', this.boundFunction); - } - - var locale = this.constants.locales[this.constants.locale]; - - this._unselectAll(); - this.forceAppendSelection = false; - this.blockConnectingEdgeSelection = true; + exports._addSector = function(node) { + // this is the currently active sector + var sector = this._sector(); - this.manipulationDOM = {}; - this.manipulationDOM['backSpan'] = document.createElement('span'); - this.manipulationDOM['backSpan'].className = 'network-manipulationUI back'; - this.manipulationDOM['backLabelSpan'] = document.createElement('span'); - this.manipulationDOM['backLabelSpan'].className = 'network-manipulationLabel'; - this.manipulationDOM['backLabelSpan'].innerHTML = locale['back']; - this.manipulationDOM['backSpan'].appendChild(this.manipulationDOM['backLabelSpan']); + // // this should allow me to select nodes from a frozen set. + // if (this.sectors['active'][sector]["nodes"].hasOwnProperty(node.id)) { + // console.log("the node is part of the active sector"); + // } + // else { + // console.log("I dont know what the fuck happened!!"); + // } - this.manipulationDOM['seperatorLineDiv1'] = document.createElement('div'); - this.manipulationDOM['seperatorLineDiv1'].className = 'network-seperatorLine'; + // 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]; - this.manipulationDOM['descriptionSpan'] = document.createElement('span'); - this.manipulationDOM['descriptionSpan'].className = 'network-manipulationUI none'; - this.manipulationDOM['descriptionLabelSpan'] = document.createElement('span'); - this.manipulationDOM['descriptionLabelSpan'].className = 'network-manipulationLabel'; - this.manipulationDOM['descriptionLabelSpan'].innerHTML = locale['edgeDescription']; - this.manipulationDOM['descriptionSpan'].appendChild(this.manipulationDOM['descriptionLabelSpan']); + var unqiueIdentifier = util.randomUUID(); - this.manipulationDiv.appendChild(this.manipulationDOM['backSpan']); - this.manipulationDiv.appendChild(this.manipulationDOM['seperatorLineDiv1']); - this.manipulationDiv.appendChild(this.manipulationDOM['descriptionSpan']); + // we fully freeze the currently active sector + this._freezeSector(sector); - // bind the icon - this.manipulationDOM['backSpan'].onclick = this._createManipulatorBar.bind(this); + // we create a new active sector. This sector has the Id of the node to ensure uniqueness + this._createNewSector(unqiueIdentifier); - // we use the boundFunction so we can reference it when we unbind it from the "select" event. - var me = this; - this.boundFunction = me._handleConnect; - this.on('select', this.boundFunction); + // we add the active sector to the sectors array to be able to revert these steps later on + this._setActiveSector(unqiueIdentifier); - // temporarily overload functions - this.cachedFunctions["_handleTouch"] = this._handleTouch; - this.cachedFunctions["_manipulationReleaseOverload"] = this._manipulationReleaseOverload; - this.cachedFunctions["_handleDragStart"] = this._handleDragStart; - this.cachedFunctions["_handleDragEnd"] = this._handleDragEnd; - this.cachedFunctions["_handleOnHold"] = this._handleOnHold; - this._handleTouch = this._handleConnect; - this._manipulationReleaseOverload = function () {}; - this._handleOnHold = function () {}; - this._handleDragStart = function () {}; - this._handleDragEnd = this._finishConnect; + // we redirect the global references to the new sector's references. this._sector() now returns unqiueIdentifier + this._switchToSector(this._sector()); - // redraw to show the unselect - this._redraw(); + // finally we add the node we removed from our previous active sector to the new active sector + this.nodes[node.id] = node; }; + /** - * create the toolbar to edit edges + * We close the sector that is currently open and revert back to the one before. + * If the active sector is the "default" sector, nothing happens. * * @private */ - exports._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(); - - var locale = this.constants.locales[this.constants.locale]; - - this.manipulationDOM = {}; - this.manipulationDOM['backSpan'] = document.createElement('span'); - this.manipulationDOM['backSpan'].className = 'network-manipulationUI back'; - this.manipulationDOM['backLabelSpan'] = document.createElement('span'); - this.manipulationDOM['backLabelSpan'].className = 'network-manipulationLabel'; - this.manipulationDOM['backLabelSpan'].innerHTML = locale['back']; - this.manipulationDOM['backSpan'].appendChild(this.manipulationDOM['backLabelSpan']); + exports._collapseSector = function() { + // the currently active sector + var sector = this._sector(); - this.manipulationDOM['seperatorLineDiv1'] = document.createElement('div'); - this.manipulationDOM['seperatorLineDiv1'].className = 'network-seperatorLine'; + // 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.manipulationDOM['descriptionSpan'] = document.createElement('span'); - this.manipulationDOM['descriptionSpan'].className = 'network-manipulationUI none'; - this.manipulationDOM['descriptionLabelSpan'] = document.createElement('span'); - this.manipulationDOM['descriptionLabelSpan'].className = 'network-manipulationLabel'; - this.manipulationDOM['descriptionLabelSpan'].innerHTML = locale['editEdgeDescription']; - this.manipulationDOM['descriptionSpan'].appendChild(this.manipulationDOM['descriptionLabelSpan']); + // we collapse the sector back to a single cluster + this._collapseThisToSingleCluster(); - this.manipulationDiv.appendChild(this.manipulationDOM['backSpan']); - this.manipulationDiv.appendChild(this.manipulationDOM['seperatorLineDiv1']); - this.manipulationDiv.appendChild(this.manipulationDOM['descriptionSpan']); + // we move the remaining nodes, edges and nodeIndices to the previous sector. + // This previous sector is the one we will reactivate + this._mergeThisWithFrozen(previousSector); - // bind the icon - this.manipulationDOM['backSpan'].onclick = this._createManipulatorBar.bind(this); + // 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); - // temporarily overload functions - this.cachedFunctions["_handleTouch"] = this._handleTouch; - this.cachedFunctions["_manipulationReleaseOverload"] = this._manipulationReleaseOverload; - 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._manipulationReleaseOverload = this._releaseControlNode; + // we activate the previously active (and currently frozen) sector. + this._activateSector(previousSector); - // redraw to show the unselect - this._redraw(); + // 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(); + } + } }; /** - * 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 runs a function in all active sectors. This is used in _redraw() and the _initializeForceCalculation(). * + * @param {String} runFunction | This is the NAME of a function we want to call in all active sectors + * | we dont pass the function itself because then the "this" is the window object + * | instead of the Network object + * @param {*} [argument] | Optional: arguments to pass to the runFunction * @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.freezeSimulationEnabled = true; + exports._doInAllActiveSectors = function(runFunction,argument) { + var returnValues = []; + 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); + returnValues.push( this[runFunction]() ); + } + } } - this._redraw(); + 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) { + returnValues.push( this[runFunction](args[0],args[1]) ); + } + else { + returnValues.push( this[runFunction](argument) ); + } + } + } + } + // we revert the global references back to our active sector + this._loadLatestSector(); + return returnValues; }; /** - * 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 runs a function in all active sectors. This is used in _redraw() and the _initializeForceCalculation(). * + * @param {String} runFunction | This is the NAME of a function we want to call in all active sectors + * | we dont pass the function itself because then the "this" is the window object + * | instead of the Network object + * @param {*} [argument] | Optional: arguments to pass to the runFunction * @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._doInSupportSector = function(runFunction,argument) { + var returnValues = false; + if (argument === undefined) { + this._switchToSupportSector(); + returnValues = this[runFunction](); } - this._redraw(); + else { + this._switchToSupportSector(); + var args = Array.prototype.splice.call(arguments, 1); + if (args.length > 1) { + returnValues = this[runFunction](args[0],args[1]); + } + else { + returnValues = this[runFunction](argument); + } + } + // we revert the global references back to our active sector + this._loadLatestSector(); + return returnValues; }; /** + * This runs a function in all frozen sectors. This is used in the _redraw(). * - * @param pointer + * @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._releaseControlNode = function(pointer) { - var newNode = this._getNodeAt(pointer); - if (newNode !== null) { - if (this.edgeBeingEdited.controlNodes.from.selected == true) { - this.edgeBeingEdited._restoreControlNodes(); - this._editEdge(newNode.id, this.edgeBeingEdited.to.id); - this.edgeBeingEdited.controlNodes.from.unselect(); - } - if (this.edgeBeingEdited.controlNodes.to.selected == true) { - this.edgeBeingEdited._restoreControlNodes(); - this._editEdge(this.edgeBeingEdited.from.id, newNode.id); - this.edgeBeingEdited.controlNodes.to.unselect(); + exports._doInAllFrozenSectors = function(runFunction,argument) { + if (argument === undefined) { + for (var sector in this.sectors["frozen"]) { + if (this.sectors["frozen"].hasOwnProperty(sector)) { + // switch the global references to those of this sector + this._switchToFrozenSector(sector); + this[runFunction](); + } } } else { - this.edgeBeingEdited._restoreControlNodes(); + 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); + } + } + } } - this.freezeSimulationEnabled = false; - this._redraw(); + this._loadLatestSector(); }; + /** - * 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 runs a function in all sectors. This is used in the _redraw(). * + * @param {String} runFunction | This is the NAME of a function we want to call in all active sectors + * | we don't pass the function itself because then the "this" is the window object + * | instead of the Network object + * @param {*} [argument] | Optional: arguments to pass to the runFunction * @private */ - exports._handleConnect = function(pointer) { - if (this._getSelectedNodeCount() == 0) { - var node = this._getNodeAt(pointer); + 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); + } + } + }; - if (node != null) { - if (node.clusterSize > 1) { - alert(this.constants.locales[this.constants.locale]['createEdgeError']) - } - else { - this._selectObject(node,false); - var supportNodes = this.sectors['support']['nodes']; - // create a node the temporary line can look at - supportNodes['targetNode'] = new Node({id:'targetNode'},{},{},this.constants); - var targetNode = supportNodes['targetNode']; - targetNode.x = node.x; - targetNode.y = node.y; + /** + * 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"]; + }; - // create a temporary edge - this.edges['connectionEdge'] = new Edge({id:"connectionEdge",from:node.id,to:targetNode.id}, this, this.constants); - var connectionEdge = this.edges['connectionEdge']; - connectionEdge.from = node; - connectionEdge.connected = true; - connectionEdge.options.smoothCurves = {enabled: true, - dynamic: false, - type: "continuous", - roundness: 0.5 - }; - connectionEdge.selected = true; - connectionEdge.to = targetNode; - this.cachedFunctions["_handleOnDrag"] = this._handleOnDrag; - this._handleOnDrag = function(event) { - var pointer = this._getPointer(event.gesture.center); - var connectionEdge = this.edges['connectionEdge']; - connectionEdge.to.x = this._XconvertDOMtoCanvas(pointer.x); - connectionEdge.to.y = this._YconvertDOMtoCanvas(pointer.y); - }; + /** + * Draw the encompassing sector node + * + * @param ctx + * @param sectorType + * @private + */ + exports._drawSectorNodes = function(ctx,sectorType) { + var minY = 1e9, maxY = -1e9, minX = 1e9, maxX = -1e9, node; + for (var sector in this.sectors[sectorType]) { + if (this.sectors[sectorType].hasOwnProperty(sector)) { + if (this.sectors[sectorType][sector]["drawingNode"] !== undefined) { - this.moving = true; - this.start(); + 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.options.radius = Math.sqrt(Math.pow(0.5*node.width,2) + Math.pow(0.5*node.height,2)); + node.setScale(this.scale); + node._drawCircle(ctx); } } } }; - exports._finishConnect = function(event) { - if (this._getSelectedNodeCount() == 1) { - var pointer = this._getPointer(event.gesture.center); - // restore the drag function - this._handleOnDrag = this.cachedFunctions["_handleOnDrag"]; - delete this.cachedFunctions["_handleOnDrag"]; + exports._drawAllSectorNodes = function(ctx) { + this._drawSectorNodes(ctx,"frozen"); + this._drawSectorNodes(ctx,"active"); + this._loadLatestSector(); + }; - // 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']; +/***/ }, +/* 66 */ +/***/ function(module, exports, __webpack_require__) { - var node = this._getNodeAt(pointer); - if (node != null) { - if (node.clusterSize > 1) { - alert(this.constants.locales[this.constants.locale]["createEdgeError"]) - } - else { - this._createEdge(connectFromId,node.id); - this._createManipulatorBar(); + var Node = __webpack_require__(56); + + /** + * 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); } } - this._unselectAll(); } }; + /** + * 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; + }; + /** - * Adds a node on the specified location + * 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._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 { - throw new Error('The function for add does not support two arguments (data,callback)'); - this._createManipulatorBar(); - this.moving = true; - this.start(); - } - } - else { - this.nodesData.add(defaultData); - this._createManipulatorBar(); - this.moving = true; - this.start(); - } - } + 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 + }; }; /** - * connect two nodes with a new edge. + * Get the top node at the a specific point (like a click) * + * @param {{x: Number, y: Number}} pointer + * @return {Node | null} node * @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 { - throw new Error('The function for connect does not support two arguments (data,callback)'); - this.moving = true; - this.start(); - } - } - else { - this.edgesData.add(defaultData); - this.moving = true; - this.start(); - } + 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; } }; + /** - * connect two nodes with a new edge. - * + * 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._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 { - throw new Error('The function for edit does not support two arguments (data, callback)'); - this.moving = true; - this.start(); + 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); } } - else { - this.edgesData.update(defaultData); - this.moving = true; - this.start(); - } } }; + /** - * Create the toolbar to edit the selected node. The label and the color can be changed. Other colors are derived from the chosen color. + * 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; + }; + + /** + * 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._editNode = function() { - if (this.triggerFunctions.edit && this.editMode == true) { - var node = this._getSelectedNode(); - var data = {id:node.id, - label: node.label, - group: node.options.group, - shape: node.options.shape, - color: { - background:node.options.color.background, - border:node.options.color.border, - highlight: { - background:node.options.color.highlight.background, - border:node.options.color.highlight.border - } - }}; - if (this.triggerFunctions.edit.length == 2) { - var me = this; - this.triggerFunctions.edit(data, function (finalizedData) { - me.nodesData.update(finalizedData); - me._createManipulatorBar(); - me.moving = true; - me.start(); - }); - } - else { - throw new Error('The function for edit does not support two arguments (data, callback)'); - } + exports._getEdgeAt = function(pointer) { + var positionObject = this._pointerToPositionObject(pointer); + var overlappingEdges = this._getAllEdgesOverlappingWith(positionObject); + + if (overlappingEdges.length > 0) { + return this.edges[overlappingEdges[overlappingEdges.length - 1]]; } else { - throw new Error('No edit function has been bound to this button'); + return null; } }; - - /** - * delete everything in the selection + * Add object to the selection array. * + * @param obj * @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 { - throw new Error('The function for delete does not support two arguments (data, callback)') - } - } - else { - this.edgesData.remove(selectedEdges); - this.nodesData.remove(selectedNodes); - this._unselectAll(); - this.moving = true; - this.start(); - } - } - else { - alert(this.constants.locales[this.constants.locale]["deleteClusterError"]); - } + exports._addToSelection = function(obj) { + if (obj instanceof Node) { + this.selectionObj.nodes[obj.id] = obj; + } + else { + this.selectionObj.edges[obj.id] = obj; + } + }; + + /** + * Add object to the selection array. + * + * @param obj + * @private + */ + exports._addToHover = function(obj) { + if (obj instanceof Node) { + this.hoverObj.nodes[obj.id] = obj; + } + else { + this.hoverObj.edges[obj.id] = obj; } }; -/***/ }, -/* 64 */ -/***/ function(module, exports, __webpack_require__) { - - var util = __webpack_require__(1); - var Hammer = __webpack_require__(45); - - exports._cleanNavigation = function() { - // clean hammer bindings - if (this.navigationHammers.existing.length != 0) { - for (var i = 0; i < this.navigationHammers.existing.length; i++) { - this.navigationHammers.existing[i].dispose(); - } - this.navigationHammers.existing = []; + /** + * Remove a single option from selection. + * + * @param {Object} obj + * @private + */ + exports._removeFromSelection = function(obj) { + if (obj instanceof Node) { + delete this.selectionObj.nodes[obj.id]; } - - this._navigationReleaseOverload = function () {}; - - // clean up previous navigation items - if (this.navigationDivs && this.navigationDivs['wrapper'] && this.navigationDivs['wrapper'].parentNode) { - this.navigationDivs['wrapper'].parentNode.removeChild(this.navigationDivs['wrapper']); + else { + delete this.selectionObj.edges[obj.id]; } }; /** - * 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. + * Unselect all. The selectionObj is useful for this. * + * @param {Boolean} [doNotTrigger] | ignore trigger * @private */ - 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.frame.appendChild(this.navigationDivs['wrapper']); - - for (var i = 0; i < navigationDivs.length; i++) { - this.navigationDivs[navigationDivs[i]] = document.createElement('div'); - this.navigationDivs[navigationDivs[i]].className = 'network-navigation ' + navigationDivs[i]; - this.navigationDivs['wrapper'].appendChild(this.navigationDivs[navigationDivs[i]]); - - var hammer = Hammer(this.navigationDivs[navigationDivs[i]], {prevent_default: true}); - hammer.on('touch', this[navigationDivActions[i]].bind(this)); - this.navigationHammers._new.push(hammer); + 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._navigationReleaseOverload = this._stopMovement; + this.selectionObj = {nodes:{},edges:{}}; - this.navigationHammers.existing = this.navigationHammers._new; + if (doNotTrigger == false) { + this.emit('select', this.getSelection()); + } }; - /** - * this stops all movement induced by the navigation buttons + * Unselect all clusters. The selectionObj is useful for this. * + * @param {Boolean} [doNotTrigger] | ignore trigger * @private */ - exports._zoomExtent = function(event) { - this.zoomExtent({duration:700}); - event.stopPropagation(); + exports._unselectClusters = function(doNotTrigger) { + if (doNotTrigger === undefined) { + doNotTrigger = false; + } + + for (var nodeId in this.selectionObj.nodes) { + if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { + if (this.selectionObj.nodes[nodeId].clusterSize > 1) { + this.selectionObj.nodes[nodeId].unselect(); + this._removeFromSelection(this.selectionObj.nodes[nodeId]); + } + } + } + + if (doNotTrigger == false) { + this.emit('select', this.getSelection()); + } }; + /** - * this stops all movement induced by the navigation buttons + * return the number of selected nodes * + * @returns {number} * @private */ - exports._stopMovement = function() { - this._xStopMoving(); - this._yStopMoving(); - this._stopZoom(); + exports._getSelectedNodeCount = function() { + var count = 0; + for (var nodeId in this.selectionObj.nodes) { + if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { + count += 1; + } + } + return count; }; - /** - * 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. + * return the selected node * + * @returns {number} * @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 - event.preventDefault(); + exports._getSelectedNode = function() { + for (var nodeId in this.selectionObj.nodes) { + if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { + return this.selectionObj.nodes[nodeId]; + } + } + return null; }; - /** - * move the screen down + * return the selected edge + * + * @returns {number} * @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 - event.preventDefault(); + exports._getSelectedEdge = function() { + for (var edgeId in this.selectionObj.edges) { + if (this.selectionObj.edges.hasOwnProperty(edgeId)) { + return this.selectionObj.edges[edgeId]; + } + } + return null; }; /** - * move the screen left + * return the number of selected edges + * + * @returns {number} * @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 - event.preventDefault(); + exports._getSelectedEdgeCount = function() { + var count = 0; + for (var edgeId in this.selectionObj.edges) { + if (this.selectionObj.edges.hasOwnProperty(edgeId)) { + count += 1; + } + } + return count; }; /** - * move the screen right + * return the number of selected objects. + * + * @returns {number} * @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 - event.preventDefault(); + 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; }; - /** - * Zoom in, using the same method as the movement. + * Check if anything is selected + * + * @returns {boolean} * @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 - event.preventDefault(); + exports._selectionIsEmpty = function() { + for(var nodeId in this.selectionObj.nodes) { + if(this.selectionObj.nodes.hasOwnProperty(nodeId)) { + return false; + } + } + for(var edgeId in this.selectionObj.edges) { + if(this.selectionObj.edges.hasOwnProperty(edgeId)) { + return false; + } + } + return true; }; /** - * Zoom out + * check if one of the selected nodes is a cluster. + * + * @returns {boolean} * @private */ - exports._zoomOut = function(event) { - this.zoomIncrement = -this.constants.keyboard.speed.zoom; - this.start(); // if there is no node movement, the calculation wont be done - event.preventDefault(); + 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; }; - /** - * Stop zooming and unhighlight the zoom controls + * select the edges connected to the node that is being selected + * + * @param {Node} node * @private */ - exports._stopZoom = function(event) { - this.zoomIncrement = 0; - event && event.preventDefault(); + exports._selectConnectedEdges = function(node) { + for (var i = 0; i < node.edges.length; i++) { + var edge = node.edges[i]; + edge.select(); + this._addToSelection(edge); + } }; - /** - * Stop moving in the Y direction and unHighlight the up and down + * select the edges connected to the node that is being selected + * + * @param {Node} node * @private */ - exports._yStopMoving = function(event) { - this.yIncrement = 0; - event && event.preventDefault(); + exports._hoverConnectedEdges = function(node) { + for (var i = 0; i < node.edges.length; i++) { + var edge = node.edges[i]; + edge.hover = true; + this._addToHover(edge); + } }; /** - * Stop moving in the X direction and unHighlight left and right. + * unselect the edges connected to the node that is being selected + * + * @param {Node} node * @private */ - exports._xStopMoving = function(event) { - this.xIncrement = 0; - event && event.preventDefault(); + exports._unselectConnectedEdges = function(node) { + for (var i = 0; i < node.edges.length; i++) { + var edge = node.edges[i]; + edge.unselect(); + this._removeFromSelection(edge); + } }; -/***/ }, -/* 65 */ -/***/ 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; - node.hierarchyEnumerated = false; - } - } - } - }; /** - * This is the main function to layout the nodes in a hierarchical way. - * It checks if the node details are supplied correctly + * 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 * @private */ - exports._setupHierarchicalLayout = function() { - if (this.constants.hierarchicalLayout.enabled == true && this.nodeIndices.length > 0) { - // get the size of the largest hubs and check if the user has defined a level for a node. - var hubsize = 0; - var node, nodeId; - var definedLevel = false; - var undefinedLevel = false; + exports._selectObject = function(object, append, doNotTrigger, highlightEdges, overrideSelectable) { + if (doNotTrigger === undefined) { + doNotTrigger = false; + } + if (highlightEdges === undefined) { + highlightEdges = true; + } - 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 (this._selectionIsEmpty() == false && append == false && this.forceAppendSelection == false) { + this._unselectAll(true); + } - // if the user defined some levels but not all, alert and run without hierarchical layout - if (undefinedLevel == true && definedLevel == true) { - throw new Error("To use the hierarchical layout, nodes require either no predefined levels or levels have to be defined for all nodes."); - this.zoomExtent({duration:0},true,this.constants.clustering.enabled); - if (!this.constants.clustering.enabled) { - this.start(); - } + // selectable allows the object to be selected. Override can be used if needed to bypass this. + if (object.selected == false && (this.constants.selectable == true || overrideSelectable)) { + object.select(); + this._addToSelection(object); + if (object instanceof Node && this.blockConnectingEdgeSelection == false && highlightEdges == true) { + this._selectConnectedEdges(object); } - else { - // setup the system to use hierarchical method. - this._changeConstants(); - - // define levels if undefined by the users. Based on hubsize - if (undefinedLevel == true) { - if (this.constants.hierarchicalLayout.layout == "hubsize") { - this._determineLevels(hubsize); - } - else { - this._determineLevelsDirected(false); - } - - } - // check the distribution of the nodes per level. - var distribution = this._getDistribution(); - - // place the nodes on the canvas. This also stablilizes the system. - this._placeNodesByHierarchy(distribution); + } + // do not select the object if selectable is false, only add it to selection to allow drag to work + else if (object.selected == false) { + this._addToSelection(object); + doNotTrigger = true; + } + else { + object.unselect(); + this._removeFromSelection(object); + } - // start the simulation. - this.start(); - } + if (doNotTrigger == false) { + this.emit('select', this.getSelection()); } }; /** - * This function places the nodes on the canvas based on the hierarchial distribution. + * 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 {Object} distribution | obtained by the function this._getDistribution() + * @param {Node || Edge} object * @private */ - exports._placeNodesByHierarchy = function(distribution) { - var nodeId, node; - - // start placing all the level 0 nodes first. Then recursively position their branches. - for (var level in distribution) { - if (distribution.hasOwnProperty(level)) { - - for (nodeId in distribution[level].nodes) { - if (distribution[level].nodes.hasOwnProperty(nodeId)) { - node = distribution[level].nodes[nodeId]; - if (this.constants.hierarchicalLayout.direction == "UD" || this.constants.hierarchicalLayout.direction == "DU") { - if (node.xFixed) { - node.x = distribution[level].minPos; - node.xFixed = false; - - 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); - } - } - } + exports._blurObject = function(object) { + if (object.hover == true) { + object.hover = false; + this.emit("blurNode",{node:object.id}); } - - // stabilize the system after positioning. This function calls zoomExtent. - this._stabilize(); }; - /** - * This function get the distribution of levels based on hubsize + * This is called when someone clicks on a node. either select or deselect it. + * If there is an existing selection and we don't want to append to it, clear the existing selection * - * @returns {Object} + * @param {Node || Edge} object * @private */ - exports._getDistribution = function() { - var distribution = {}; - var nodeId, node, level; - - // we fix Y because the hierarchy is vertical, we fix X so we do not give a node an x position for a second time. - // the fix of X is removed after the x value has been set. - for (nodeId in this.nodes) { - if (this.nodes.hasOwnProperty(nodeId)) { - node = this.nodes[nodeId]; - node.xFixed = true; - node.yFixed = true; - if (this.constants.hierarchicalLayout.direction == "UD" || this.constants.hierarchicalLayout.direction == "DU") { - node.y = this.constants.hierarchicalLayout.levelSeparation*node.level; - } - else { - node.x = this.constants.hierarchicalLayout.levelSeparation*node.level; - } - if (distribution[node.level] === undefined) { - distribution[node.level] = {amount: 0, nodes: {}, minPos:0, nodeSpacing:0}; - } - distribution[node.level].amount += 1; - distribution[node.level].nodes[nodeId] = node; + exports._hoverObject = function(object) { + if (object.hover == false) { + object.hover = true; + this._addToHover(object); + if (object instanceof Node) { + this.emit("hoverNode",{node:object.id}); } } - - // 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; - } - } + if (object instanceof Node) { + this._hoverConnectedEdges(object); } + }; - // set the initial position and spacing of each nodes accordingly - for (level in distribution) { - if (distribution.hasOwnProperty(level)) { - distribution[level].nodeSpacing = (maxCount + 1) * this.constants.hierarchicalLayout.nodeSpacing; - distribution[level].nodeSpacing /= (distribution[level].amount + 1); - distribution[level].minPos = distribution[level].nodeSpacing - (0.5 * (distribution[level].amount + 1) * distribution[level].nodeSpacing); - } - } - return distribution; + /** + * 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._handleTouch = function(pointer) { }; /** - * this function allocates nodes in levels based on the recursive branching from the largest hubs. + * handles the selection part of the tap; * - * @param hubsize + * @param {Object} pointer * @private */ - exports._determineLevels = function(hubsize) { - var nodeId, node; - - // determine hubs - for (nodeId in this.nodes) { - if (this.nodes.hasOwnProperty(nodeId)) { - node = this.nodes[nodeId]; - if (node.edges.length == hubsize) { - node.level = 0; - } - } + exports._handleTap = function(pointer) { + var node = this._getNodeAt(pointer); + if (node != null) { + this._selectObject(node, false); } - - // 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); - } + else { + var edge = this._getEdgeAt(pointer); + if (edge != null) { + this._selectObject(edge, false); + } + else { + this._unselectAll(); } } + var properties = this.getSelection(); + properties['pointer'] = { + DOM: {x: pointer.x, y: pointer.y}, + canvas: {x: this._XconvertDOMtoCanvas(pointer.x), y: this._YconvertDOMtoCanvas(pointer.y)} + } + this.emit("click", properties); + this._requestRedraw(); }; - /** - * this function allocates nodes in levels based on the direction of the edges + * handles the selection part of the double tap and opens a cluster if needed * - * @param hubsize + * @param {Object} pointer * @private */ - exports._determineLevelsDirected = function() { - var nodeId, node, firstNode; - var minLevel = 10000; - - // set first node to source - firstNode = this.nodes[this.nodeIndices[0]]; - firstNode.level = minLevel; - this._setLevelDirected(minLevel,firstNode.edges,firstNode.id); - - // get the minimum level - for (nodeId in this.nodes) { - if (this.nodes.hasOwnProperty(nodeId)) { - node = this.nodes[nodeId]; - minLevel = node.level < minLevel ? node.level : minLevel; - } + 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); } - - // subtract the minimum from the set so we have a range starting from 0 - for (nodeId in this.nodes) { - if (this.nodes.hasOwnProperty(nodeId)) { - node = this.nodes[nodeId]; - node.level -= minLevel; - } + var properties = this.getSelection(); + properties['pointer'] = { + DOM: {x: pointer.x, y: pointer.y}, + canvas: {x: this._XconvertDOMtoCanvas(pointer.x), y: this._YconvertDOMtoCanvas(pointer.y)} } + this.emit("doubleClick", properties); }; /** - * 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. + * Handle the onHold selection part * + * @param pointer * @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(); - - var config = this.constants.hierarchicalLayout; - config.levelSeparation = Math.abs(config.levelSeparation); - if (config.direction == "RL" || config.direction == "DU") { - config.levelSeparation *= -1; - } - - if (config.direction == "RL" || config.direction == "LR") { - if (this.constants.smoothCurves.enabled == true) { - this.constants.smoothCurves.type = "vertical"; - } + exports._handleOnHold = function(pointer) { + var node = this._getNodeAt(pointer); + if (node != null) { + this._selectObject(node,true); } else { - if (this.constants.smoothCurves.enabled == true) { - this.constants.smoothCurves.type = "horizontal"; + var edge = this._getEdgeAt(pointer); + if (edge != null) { + this._selectObject(edge,true); } } + this._requestRedraw(); }; /** - * 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. + * handle the onRelease event. These functions are here for the navigation controls module + * and data manipulation module. * - * @param edges - * @param parentId - * @param distribution - * @param parentLevel - * @private + * @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._handleOnRelease = function(pointer) { + this._manipulationReleaseOverload(pointer); + this._navigationReleaseOverload(pointer); + }; - // 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; - } - } + exports._manipulationReleaseOverload = function (pointer) {}; + exports._navigationReleaseOverload = function (pointer) {}; - 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); + /** + * + * 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 = []; + if (this.constants.selectable == true) { + for (var nodeId in this.selectionObj.nodes) { + if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { + idArray.push(nodeId); } } } + return idArray }; - /** - * 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 + * retrieve the currently selected edges + * @return {Array} selection An array with the ids of the + * selected nodes. */ - 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 (childNode.edges.length > 1) { - this._setLevel(level+1, childNode.edges, childNode.id); + exports.getSelectedEdges = function() { + var idArray = []; + if (this.constants.selectable == true) { + for (var edgeId in this.selectionObj.edges) { + if (this.selectionObj.edges.hasOwnProperty(edgeId)) { + idArray.push(edgeId); } } } + return idArray; }; /** - * this function is called recursively to enumerate the branched of the first node and give each node a level based on edge direction - * - * @param level - * @param edges - * @param parentId - * @private + * select zero or more nodes DEPRICATED + * @param {Number[] | String[]} selection An array with the ids of the + * selected nodes. */ - exports._setLevelDirected = function(level, edges, parentId) { - this.nodes[parentId].hierarchyEnumerated = true; - var childNode, direction; - for (var i = 0; i < edges.length; i++) { - direction = 1; - if (edges[i].toId == parentId) { - childNode = edges[i].from; - direction = -1; - } - else { - childNode = edges[i].to; - } - if (childNode.level == -1) { - childNode.level = level + direction; + exports.setSelection = function() { + console.log("setSelection is deprecated. Please use selectNodes instead.") + }; + + + /** + * 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.selectNodes = function(selection, highlightEdges) { + var i, iMax, id; + + if (!selection || (selection.length == undefined)) + throw 'Selection must be an array with ids'; + + // first unselect any selected node + this._unselectAll(true); + + for (i = 0, iMax = selection.length; i < iMax; i++) { + id = selection[i]; + + var node = this.nodes[id]; + if (!node) { + throw new RangeError('Node with id "' + id + '" not found'); } + this._selectObject(node,true,true,highlightEdges,true); } + this.redraw(); + }; - for (var i = 0; i < edges.length; i++) { - if (edges[i].toId == parentId) {childNode = edges[i].from;} - else {childNode = edges[i].to;} - if (childNode.edges.length > 1 && childNode.hierarchyEnumerated === false) { - this._setLevelDirected(childNode.level, childNode.edges, childNode.id); + /** + * 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; + + 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 edge = this.edges[id]; + if (!edge) { + throw new RangeError('Edge with id "' + id + '" not found'); } + this._selectObject(edge,true,true,false,true); } + this.redraw(); }; - /** - * Unfix nodes - * + * Validate the selection: remove ids of nodes which no longer exist * @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; + 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]; + } } } }; /***/ }, -/* 66 */ +/* 67 */ /***/ function(module, exports, __webpack_require__) { var util = __webpack_require__(1); - var RepulsionMixin = __webpack_require__(68); - var HierarchialRepulsionMixin = __webpack_require__(69); - var BarnesHutMixin = __webpack_require__(70); + var Node = __webpack_require__(56); + var Edge = __webpack_require__(57); /** - * Toggling barnes Hut calculation on and off. + * clears the toolbar div element of children * * @private */ - exports._toggleBarnesHut = function () { - this.constants.physics.barnesHut.enabled = !this.constants.physics.barnesHut.enabled; - this._loadSelectedForceSolver(); - this.moving = true; - this.start(); - }; + exports._clearManipulatorBar = function() { + this._recursiveDOMDelete(this.manipulationDiv); + this.manipulationDOM = {}; + this._manipulationReleaseOverload = function () {}; + delete this.sectors['support']['nodes']['targetNode']; + delete this.sectors['support']['nodes']['targetViaNode']; + this.controlNodesActive = false; + this.freezeSimulationEnabled = false; + }; /** - * This loads the node force solver based on the barnes hut or repulsion algorithm + * 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._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); + exports._restoreOverloadedFunctions = function() { + for (var functionName in this.cachedFunctions) { + if (this.cachedFunctions.hasOwnProperty(functionName)) { + this[functionName] = this.cachedFunctions[functionName]; + delete this.cachedFunctions[functionName]; + } } - else if (this.constants.physics.hierarchicalRepulsion.enabled == true) { - this._clearMixin(BarnesHutMixin); - this._clearMixin(RepulsionMixin); - - 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); + /** + * Enable or disable edit-mode. + * + * @private + */ + exports._toggleEditMode = function() { + this.editMode = !this.editMode; + var toolbar = this.manipulationDiv; + var closeDiv = this.closeDiv; + var editModeDiv = this.editModeDiv; + if (this.editMode == true) { + toolbar.style.display="block"; + closeDiv.style.display="block"; + editModeDiv.style.display="none"; + closeDiv.onclick = this._toggleEditMode.bind(this); } else { - this._clearMixin(BarnesHutMixin); - this._clearMixin(HierarchialRepulsionMixin); - this.barnesHutTree = undefined; - - this.constants.physics.centralGravity = this.constants.physics.repulsion.centralGravity; - this.constants.physics.springLength = this.constants.physics.repulsion.springLength; - this.constants.physics.springConstant = this.constants.physics.repulsion.springConstant; - this.constants.physics.damping = this.constants.physics.repulsion.damping; - - this._loadMixin(RepulsionMixin); + toolbar.style.display="none"; + closeDiv.style.display="none"; + editModeDiv.style.display="block"; + closeDiv.onclick = null; } + this._createManipulatorBar() }; /** - * 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. + * main function, creates the main toolbar. Removes functions bound to the select event. Binds all the buttons of the toolbar. * * @private */ - exports._initializeForceCalculation = function () { - // stop calculation if there is only one node - if (this.nodeIndices.length == 1) { - this.nodes[this.nodeIndices[0]]._setForce(0, 0); + exports._createManipulatorBar = function() { + // remove bound functions + if (this.boundFunction) { + this.off('select', this.boundFunction); } - 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(); + var locale = this.constants.locales[this.constants.locale]; + + if (this.edgeBeingEdited !== undefined) { + this.edgeBeingEdited._disableControlNodes(); + this.edgeBeingEdited = undefined; + this.selectedControlNode = null; + this.controlNodesActive = false; + this._redraw(); } - }; + // restore overloaded functions + this._restoreOverloadedFunctions(); - /** - * 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 + // resume calculation + this.freezeSimulationEnabled = false; - this._calculateGravitationalForces(); - this._calculateNodeForces(); + // reset global variables + this.blockConnectingEdgeSelection = false; + this.forceAppendSelection = false; + this.manipulationDOM = {}; - 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(); - } + if (this.editMode == true) { + while (this.manipulationDiv.hasChildNodes()) { + this.manipulationDiv.removeChild(this.manipulationDiv.firstChild); } - } - }; + this.manipulationDOM['addNodeSpan'] = document.createElement('span'); + this.manipulationDOM['addNodeSpan'].className = 'network-manipulationUI add'; + this.manipulationDOM['addNodeLabelSpan'] = document.createElement('span'); + this.manipulationDOM['addNodeLabelSpan'].className = 'network-manipulationLabel'; + this.manipulationDOM['addNodeLabelSpan'].innerHTML = locale['addNode']; + this.manipulationDOM['addNodeSpan'].appendChild(this.manipulationDOM['addNodeLabelSpan']); + + this.manipulationDOM['seperatorLineDiv1'] = document.createElement('div'); + this.manipulationDOM['seperatorLineDiv1'].className = 'network-seperatorLine'; - /** - * 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 = []; + this.manipulationDOM['addEdgeSpan'] = document.createElement('span'); + this.manipulationDOM['addEdgeSpan'].className = 'network-manipulationUI connect'; + this.manipulationDOM['addEdgeLabelSpan'] = document.createElement('span'); + this.manipulationDOM['addEdgeLabelSpan'].className = 'network-manipulationLabel'; + this.manipulationDOM['addEdgeLabelSpan'].innerHTML = locale['addEdge']; + this.manipulationDOM['addEdgeSpan'].appendChild(this.manipulationDOM['addEdgeLabelSpan']); - for (var nodeId in this.nodes) { - if (this.nodes.hasOwnProperty(nodeId)) { - this.calculationNodes[nodeId] = this.nodes[nodeId]; - } + this.manipulationDiv.appendChild(this.manipulationDOM['addNodeSpan']); + this.manipulationDiv.appendChild(this.manipulationDOM['seperatorLineDiv1']); + this.manipulationDiv.appendChild(this.manipulationDOM['addEdgeSpan']); + + if (this._getSelectedNodeCount() == 1 && this.triggerFunctions.edit) { + this.manipulationDOM['seperatorLineDiv2'] = document.createElement('div'); + this.manipulationDOM['seperatorLineDiv2'].className = 'network-seperatorLine'; + + this.manipulationDOM['editNodeSpan'] = document.createElement('span'); + this.manipulationDOM['editNodeSpan'].className = 'network-manipulationUI edit'; + this.manipulationDOM['editNodeLabelSpan'] = document.createElement('span'); + this.manipulationDOM['editNodeLabelSpan'].className = 'network-manipulationLabel'; + this.manipulationDOM['editNodeLabelSpan'].innerHTML = locale['editNode']; + this.manipulationDOM['editNodeSpan'].appendChild(this.manipulationDOM['editNodeLabelSpan']); + + this.manipulationDiv.appendChild(this.manipulationDOM['seperatorLineDiv2']); + this.manipulationDiv.appendChild(this.manipulationDOM['editNodeSpan']); } - 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); - } - } + else if (this._getSelectedEdgeCount() == 1 && this._getSelectedNodeCount() == 0) { + this.manipulationDOM['seperatorLineDiv3'] = document.createElement('div'); + this.manipulationDOM['seperatorLineDiv3'].className = 'network-seperatorLine'; + + this.manipulationDOM['editEdgeSpan'] = document.createElement('span'); + this.manipulationDOM['editEdgeSpan'].className = 'network-manipulationUI edit'; + this.manipulationDOM['editEdgeLabelSpan'] = document.createElement('span'); + this.manipulationDOM['editEdgeLabelSpan'].className = 'network-manipulationLabel'; + this.manipulationDOM['editEdgeLabelSpan'].innerHTML = locale['editEdge']; + this.manipulationDOM['editEdgeSpan'].appendChild(this.manipulationDOM['editEdgeLabelSpan']); + + this.manipulationDiv.appendChild(this.manipulationDOM['seperatorLineDiv3']); + this.manipulationDiv.appendChild(this.manipulationDOM['editEdgeSpan']); } + if (this._selectionIsEmpty() == false) { + this.manipulationDOM['seperatorLineDiv4'] = document.createElement('div'); + this.manipulationDOM['seperatorLineDiv4'].className = 'network-seperatorLine'; - for (var idx in this.calculationNodes) { - if (this.calculationNodes.hasOwnProperty(idx)) { - this.calculationNodeIndices.push(idx); - } + this.manipulationDOM['deleteSpan'] = document.createElement('span'); + this.manipulationDOM['deleteSpan'].className = 'network-manipulationUI delete'; + this.manipulationDOM['deleteLabelSpan'] = document.createElement('span'); + this.manipulationDOM['deleteLabelSpan'].className = 'network-manipulationLabel'; + this.manipulationDOM['deleteLabelSpan'].innerHTML = locale['del']; + this.manipulationDOM['deleteSpan'].appendChild(this.manipulationDOM['deleteLabelSpan']); + + this.manipulationDiv.appendChild(this.manipulationDOM['seperatorLineDiv4']); + this.manipulationDiv.appendChild(this.manipulationDOM['deleteSpan']); + } + + + // bind the icons + this.manipulationDOM['addNodeSpan'].onclick = this._createAddNodeToolbar.bind(this); + this.manipulationDOM['addEdgeSpan'].onclick = this._createAddEdgeToolbar.bind(this); + if (this._getSelectedNodeCount() == 1 && this.triggerFunctions.edit) { + this.manipulationDOM['editNodeSpan'].onclick = this._editNode.bind(this); + } + else if (this._getSelectedEdgeCount() == 1 && this._getSelectedNodeCount() == 0) { + this.manipulationDOM['editEdgeSpan'].onclick = this._createEditEdgeToolbar.bind(this); } + if (this._selectionIsEmpty() == false) { + this.manipulationDOM['deleteSpan'].onclick = this._deleteSelected.bind(this); + } + this.closeDiv.onclick = this._toggleEditMode.bind(this); + + var me = this; + this.boundFunction = me._createManipulatorBar; + this.on('select', this.boundFunction); } else { - this.calculationNodes = this.nodes; - this.calculationNodeIndices = this.nodeIndices; + while (this.editModeDiv.hasChildNodes()) { + this.editModeDiv.removeChild(this.editModeDiv.firstChild); + } + + this.manipulationDOM['editModeSpan'] = document.createElement('span'); + this.manipulationDOM['editModeSpan'].className = 'network-manipulationUI edit editmode'; + this.manipulationDOM['editModeLabelSpan'] = document.createElement('span'); + this.manipulationDOM['editModeLabelSpan'].className = 'network-manipulationLabel'; + this.manipulationDOM['editModeLabelSpan'].innerHTML = locale['edit']; + this.manipulationDOM['editModeSpan'].appendChild(this.manipulationDOM['editModeLabelSpan']); + + this.editModeDiv.appendChild(this.manipulationDOM['editModeSpan']); + + this.manipulationDOM['editModeSpan'].onclick = this._toggleEditMode.bind(this); } }; + /** - * this function applies the central gravity effect to keep groups from floating off + * Create the toolbar for adding Nodes * * @private */ - exports._calculateGravitationalForces = function () { - var dx, dy, distance, node, i; - var nodes = this.calculationNodes; - var gravity = this.constants.physics.centralGravity; - var gravityForce = 0; + exports._createAddNodeToolbar = function() { + // clear the toolbar + this._clearManipulatorBar(); + if (this.boundFunction) { + this.off('select', this.boundFunction); + } - 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); + var locale = this.constants.locales[this.constants.locale]; - gravityForce = (distance == 0) ? 0 : (gravity / distance); - node.fx = dx * gravityForce; - node.fy = dy * gravityForce; - } - else { - node.fx = 0; - node.fy = 0; - } - } - }; + this.manipulationDOM = {}; + this.manipulationDOM['backSpan'] = document.createElement('span'); + this.manipulationDOM['backSpan'].className = 'network-manipulationUI back'; + this.manipulationDOM['backLabelSpan'] = document.createElement('span'); + this.manipulationDOM['backLabelSpan'].className = 'network-manipulationLabel'; + this.manipulationDOM['backLabelSpan'].innerHTML = locale['back']; + this.manipulationDOM['backSpan'].appendChild(this.manipulationDOM['backLabelSpan']); + this.manipulationDOM['seperatorLineDiv1'] = document.createElement('div'); + this.manipulationDOM['seperatorLineDiv1'].className = 'network-seperatorLine'; + + this.manipulationDOM['descriptionSpan'] = document.createElement('span'); + this.manipulationDOM['descriptionSpan'].className = 'network-manipulationUI none'; + this.manipulationDOM['descriptionLabelSpan'] = document.createElement('span'); + this.manipulationDOM['descriptionLabelSpan'].className = 'network-manipulationLabel'; + this.manipulationDOM['descriptionLabelSpan'].innerHTML = locale['addDescription']; + this.manipulationDOM['descriptionSpan'].appendChild(this.manipulationDOM['descriptionLabelSpan']); + + this.manipulationDiv.appendChild(this.manipulationDOM['backSpan']); + this.manipulationDiv.appendChild(this.manipulationDOM['seperatorLineDiv1']); + this.manipulationDiv.appendChild(this.manipulationDOM['descriptionSpan']); + + // bind the icon + this.manipulationDOM['backSpan'].onclick = this._createManipulatorBar.bind(this); + // we use the boundFunction so we can reference it when we unbind it from the "select" event. + var me = this; + this.boundFunction = me._addNode; + this.on('select', this.boundFunction); + }; /** - * this function calculates the effects of the springs in the case of unsmooth curves. + * create the toolbar to connect nodes * * @private */ - exports._calculateSpringForces = function () { - var edgeLength, edge, edgeId; - var dx, dy, fx, fy, springForce, distance; - var edges = this.edges; + exports._createAddEdgeToolbar = function() { + // clear the toolbar + this._clearManipulatorBar(); + this._unselectAll(true); + this.freezeSimulationEnabled = 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)) { - edgeLength = edge.physics.springLength; - // this implies that the edges between big clusters are longer - edgeLength += (edge.to.clusterSize + edge.from.clusterSize - 2) * this.constants.clustering.edgeGrowth; + if (this.boundFunction) { + this.off('select', this.boundFunction); + } - dx = (edge.from.x - edge.to.x); - dy = (edge.from.y - edge.to.y); - distance = Math.sqrt(dx * dx + dy * dy); + var locale = this.constants.locales[this.constants.locale]; - if (distance == 0) { - distance = 0.01; - } + this._unselectAll(); + this.forceAppendSelection = false; + this.blockConnectingEdgeSelection = true; - // the 1/distance is so the fx and fy can be calculated without sine or cosine. - springForce = this.constants.physics.springConstant * (edgeLength - distance) / distance; + this.manipulationDOM = {}; + this.manipulationDOM['backSpan'] = document.createElement('span'); + this.manipulationDOM['backSpan'].className = 'network-manipulationUI back'; + this.manipulationDOM['backLabelSpan'] = document.createElement('span'); + this.manipulationDOM['backLabelSpan'].className = 'network-manipulationLabel'; + this.manipulationDOM['backLabelSpan'].innerHTML = locale['back']; + this.manipulationDOM['backSpan'].appendChild(this.manipulationDOM['backLabelSpan']); - fx = dx * springForce; - fy = dy * springForce; + this.manipulationDOM['seperatorLineDiv1'] = document.createElement('div'); + this.manipulationDOM['seperatorLineDiv1'].className = 'network-seperatorLine'; - edge.from.fx += fx; - edge.from.fy += fy; - edge.to.fx -= fx; - edge.to.fy -= fy; - } - } - } - } - }; + this.manipulationDOM['descriptionSpan'] = document.createElement('span'); + this.manipulationDOM['descriptionSpan'].className = 'network-manipulationUI none'; + this.manipulationDOM['descriptionLabelSpan'] = document.createElement('span'); + this.manipulationDOM['descriptionLabelSpan'].className = 'network-manipulationLabel'; + this.manipulationDOM['descriptionLabelSpan'].innerHTML = locale['edgeDescription']; + this.manipulationDOM['descriptionSpan'].appendChild(this.manipulationDOM['descriptionLabelSpan']); + + this.manipulationDiv.appendChild(this.manipulationDOM['backSpan']); + this.manipulationDiv.appendChild(this.manipulationDOM['seperatorLineDiv1']); + this.manipulationDiv.appendChild(this.manipulationDOM['descriptionSpan']); + + // bind the icon + this.manipulationDOM['backSpan'].onclick = this._createManipulatorBar.bind(this); + // we use the boundFunction so we can reference it when we unbind it from the "select" event. + var me = this; + this.boundFunction = me._handleConnect; + this.on('select', this.boundFunction); + // temporarily overload functions + this.cachedFunctions["_handleTouch"] = this._handleTouch; + this.cachedFunctions["_manipulationReleaseOverload"] = this._manipulationReleaseOverload; + this.cachedFunctions["_handleDragStart"] = this._handleDragStart; + this.cachedFunctions["_handleDragEnd"] = this._handleDragEnd; + this.cachedFunctions["_handleOnHold"] = this._handleOnHold; + this._handleTouch = this._handleConnect; + this._manipulationReleaseOverload = function () {}; + this._handleOnHold = function () {}; + this._handleDragStart = function () {}; + this._handleDragEnd = this._finishConnect; + // redraw to show the unselect + this._redraw(); + }; /** - * This function calculates the springforces on the nodes, accounting for the support nodes. + * create the toolbar to edit edges * * @private */ - exports._calculateSpringForcesWithSupport = function () { - var edgeLength, edge, edgeId, combinedClusterSize; - var edges = this.edges; + exports._createEditEdgeToolbar = function() { + // clear the toolbar + this._clearManipulatorBar(); + this.controlNodesActive = 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; + if (this.boundFunction) { + this.off('select', this.boundFunction); + } - edgeLength = edge.physics.springLength; + this.edgeBeingEdited = this._getSelectedEdge(); + this.edgeBeingEdited._enableControlNodes(); - combinedClusterSize = node1.clusterSize + node3.clusterSize - 2; + var locale = this.constants.locales[this.constants.locale]; - // 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.manipulationDOM = {}; + this.manipulationDOM['backSpan'] = document.createElement('span'); + this.manipulationDOM['backSpan'].className = 'network-manipulationUI back'; + this.manipulationDOM['backLabelSpan'] = document.createElement('span'); + this.manipulationDOM['backLabelSpan'].className = 'network-manipulationLabel'; + this.manipulationDOM['backLabelSpan'].innerHTML = locale['back']; + this.manipulationDOM['backSpan'].appendChild(this.manipulationDOM['backLabelSpan']); + + this.manipulationDOM['seperatorLineDiv1'] = document.createElement('div'); + this.manipulationDOM['seperatorLineDiv1'].className = 'network-seperatorLine'; + + this.manipulationDOM['descriptionSpan'] = document.createElement('span'); + this.manipulationDOM['descriptionSpan'].className = 'network-manipulationUI none'; + this.manipulationDOM['descriptionLabelSpan'] = document.createElement('span'); + this.manipulationDOM['descriptionLabelSpan'].className = 'network-manipulationLabel'; + this.manipulationDOM['descriptionLabelSpan'].innerHTML = locale['editEdgeDescription']; + this.manipulationDOM['descriptionSpan'].appendChild(this.manipulationDOM['descriptionLabelSpan']); + + this.manipulationDiv.appendChild(this.manipulationDOM['backSpan']); + this.manipulationDiv.appendChild(this.manipulationDOM['seperatorLineDiv1']); + this.manipulationDiv.appendChild(this.manipulationDOM['descriptionSpan']); + + // bind the icon + this.manipulationDOM['backSpan'].onclick = this._createManipulatorBar.bind(this); + + // temporarily overload functions + this.cachedFunctions["_handleTouch"] = this._handleTouch; + this.cachedFunctions["_manipulationReleaseOverload"] = this._manipulationReleaseOverload; + 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._manipulationReleaseOverload = this._releaseControlNode; + + // redraw to show the unselect + this._redraw(); }; /** - * This is the code actually performing the calculation for the function above. It is split out to avoid repetition. + * 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 node1 - * @param node2 - * @param edgeLength * @private */ - exports._calculateSpringForce = function (node1, node2, edgeLength) { - var dx, dy, fx, fy, springForce, distance; - - dx = (node1.x - node2.x); - dy = (node1.y - node2.y); - distance = Math.sqrt(dx * dx + dy * dy); - - if (distance == 0) { - distance = 0.01; + 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.freezeSimulationEnabled = true; } + 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; + /** + * the function bound to the selection event. It checks if you want to connect a cluster and changes the description + * to walk the user through the process. + * + * @private + */ + exports._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(); }; - exports._cleanupPhysicsConfiguration = function() { - if (this.physicsConfiguration !== undefined) { - while (this.physicsConfiguration.hasChildNodes()) { - this.physicsConfiguration.removeChild(this.physicsConfiguration.firstChild); + /** + * + * @param pointer + * @private + */ + exports._releaseControlNode = function(pointer) { + var newNode = this._getNodeAt(pointer); + if (newNode !== null) { + if (this.edgeBeingEdited.controlNodes.from.selected == true) { + this.edgeBeingEdited._restoreControlNodes(); + this._editEdge(newNode.id, this.edgeBeingEdited.to.id); + this.edgeBeingEdited.controlNodes.from.unselect(); + } + if (this.edgeBeingEdited.controlNodes.to.selected == true) { + this.edgeBeingEdited._restoreControlNodes(); + this._editEdge(this.edgeBeingEdited.from.id, newNode.id); + this.edgeBeingEdited.controlNodes.to.unselect(); } - - this.physicsConfiguration.parentNode.removeChild(this.physicsConfiguration); - this.physicsConfiguration = undefined; } - } + else { + this.edgeBeingEdited._restoreControlNodes(); + } + this.freezeSimulationEnabled = false; + this._redraw(); + }; /** - * Load the HTML for the physics config and bind it + * the function bound to the selection event. It checks if you want to connect a cluster and changes the description + * to walk the user through the process. + * * @private */ - exports._loadPhysicsConfiguration = function () { - if (this.physicsConfiguration === undefined) { - this.backupConstants = {}; - util.deepExtend(this.backupConstants,this.constants); - - var maxGravitational = Math.max(20000, (-1 * this.constants.physics.barnesHut.gravitationalConstant) * 10); - var maxSpring = Math.min(0.05, this.constants.physics.barnesHut.springConstant * 10) + exports._handleConnect = function(pointer) { + if (this._getSelectedNodeCount() == 0) { + var node = this._getNodeAt(pointer); - 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); + if (node != null) { + if (node.clusterSize > 1) { + alert(this.constants.locales[this.constants.locale]['createEdgeError']) + } + else { + this._selectObject(node,false); + var supportNodes = this.sectors['support']['nodes']; - 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"); + // create a node the temporary line can look at + supportNodes['targetNode'] = new Node({id:'targetNode'},{},{},this.constants); + var targetNode = supportNodes['targetNode']; + targetNode.x = node.x; + targetNode.y = node.y; - 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"); + // create a temporary edge + this.edges['connectionEdge'] = new Edge({id:"connectionEdge",from:node.id,to:targetNode.id}, this, this.constants); + var connectionEdge = this.edges['connectionEdge']; + connectionEdge.from = node; + connectionEdge.connected = true; + connectionEdge.options.smoothCurves = {enabled: true, + dynamic: false, + type: "continuous", + roundness: 0.5 + }; + connectionEdge.selected = true; + connectionEdge.to = targetNode; - 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.cachedFunctions["_handleOnDrag"] = this._handleOnDrag; + this._handleOnDrag = function(event) { + var pointer = this._getPointer(event.gesture.center); + var connectionEdge = this.edges['connectionEdge']; + connectionEdge.to.x = this._XconvertDOMtoCanvas(pointer.x); + connectionEdge.to.y = this._YconvertDOMtoCanvas(pointer.y); + }; - 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; + this.moving = true; + this.start(); + } } - if (this.constants.hierarchicalLayout.enabled) { - radioButton3.checked = true; + } + }; + + exports._finishConnect = function(event) { + if (this._getSelectedNodeCount() == 1) { + var pointer = this._getPointer(event.gesture.center); + // 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(this.constants.locales[this.constants.locale]["createEdgeError"]) + } + else { + this._createEdge(connectFromId,node.id); + this._createManipulatorBar(); + } } + this._unselectAll(); + } + }; - 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"; + /** + * Adds a node on the specified location + */ + exports._addNode = function() { + if (this._selectionIsEmpty() && this.editMode == true) { + var positionObject = this._pointerToPositionObject(this.pointerPosition); + var defaultData = {id:util.randomUUID(),x:positionObject.left,y:positionObject.top,label:"new",allowedToMoveX:true,allowedToMoveY:true}; + if (this.triggerFunctions.add) { + if (this.triggerFunctions.add.length == 2) { + var me = this; + this.triggerFunctions.add(defaultData, function(finalizedData) { + me.nodesData.add(finalizedData); + me._createManipulatorBar(); + me.moving = true; + me.start(); + }); + } + else { + throw new Error('The function for add does not support two arguments (data,callback)'); + this._createManipulatorBar(); + this.moving = true; + this.start(); + } } else { - graph_toggleSmooth.style.background = "#FF8532"; + this.nodesData.add(defaultData); + this._createManipulatorBar(); + this.moving = true; + this.start(); } - - - switchConfigurations.apply(this); - - radioButton1.onchange = switchConfigurations.bind(this); - radioButton2.onchange = switchConfigurations.bind(this); - radioButton3.onchange = switchConfigurations.bind(this); } }; + /** - * This overwrites the this.constants. + * connect two nodes with a new edge. * - * @param constantsVariableName - * @param value * @private */ - exports._overWriteGraphConstants = function (constantsVariableName, value) { - var nameArray = constantsVariableName.split("_"); - if (nameArray.length == 1) { - this.constants[nameArray[0]] = value; - } - else if (nameArray.length == 2) { - this.constants[nameArray[0]][nameArray[1]] = value; - } - else if (nameArray.length == 3) { - this.constants[nameArray[0]][nameArray[1]][nameArray[2]] = value; + exports._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 { + throw new Error('The function for connect does not support two arguments (data,callback)'); + this.moving = true; + this.start(); + } + } + else { + this.edgesData.add(defaultData); + this.moving = true; + this.start(); + } } }; - /** - * this function is bound to the toggle smooth curves button. That is also why it is not in the prototype. + * connect two nodes with a new edge. + * + * @private */ - 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); - } + 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 { + throw new Error('The function for edit does not support two arguments (data, callback)'); + this.moving = true; + this.start(); + } + } + else { + this.edgesData.update(defaultData); + this.moving = true; + this.start(); + } + } + }; /** - * this function is used to scramble the nodes + * 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 */ - 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; + exports._editNode = function() { + if (this.triggerFunctions.edit && this.editMode == true) { + var node = this._getSelectedNode(); + var data = {id:node.id, + label: node.label, + group: node.options.group, + shape: node.options.shape, + color: { + background:node.options.color.background, + border:node.options.color.border, + highlight: { + background:node.options.color.highlight.background, + border:node.options.color.highlight.border + } + }}; + if (this.triggerFunctions.edit.length == 2) { + var me = this; + this.triggerFunctions.edit(data, function (finalizedData) { + me.nodesData.update(finalizedData); + me._createManipulatorBar(); + me.moving = true; + me.start(); + }); + } + else { + throw new Error('The function for edit does not support two arguments (data, callback)'); } - } - 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(); + throw new Error('No edit function has been bound to this button'); } - this.moving = true; - this.start(); - } + }; + + + /** - * this is used to generate an options file from the playing with physics system. + * delete everything in the selection + * + * @private */ - function graphGenerateOptions () { - var options = "No options are required, default values used."; - var optionsSpecific = []; - var radioButton1 = document.getElementById("graph_physicsMethod1"); - var radioButton2 = document.getElementById("graph_physicsMethod2"); - if (radioButton1.checked == true) { - if (this.constants.physics.barnesHut.gravitationalConstant != this.backupConstants.physics.barnesHut.gravitationalConstant) {optionsSpecific.push("gravitationalConstant: " + this.constants.physics.barnesHut.gravitationalConstant);} - if (this.constants.physics.centralGravity != this.backupConstants.physics.barnesHut.centralGravity) {optionsSpecific.push("centralGravity: " + this.constants.physics.centralGravity);} - if (this.constants.physics.springLength != this.backupConstants.physics.barnesHut.springLength) {optionsSpecific.push("springLength: " + this.constants.physics.springLength);} - if (this.constants.physics.springConstant != this.backupConstants.physics.barnesHut.springConstant) {optionsSpecific.push("springConstant: " + this.constants.physics.springConstant);} - if (this.constants.physics.damping != this.backupConstants.physics.barnesHut.damping) {optionsSpecific.push("damping: " + this.constants.physics.damping);} - if (optionsSpecific.length != 0) { - options = "var options = {"; - options += "physics: {barnesHut: {"; - for (var i = 0; i < optionsSpecific.length; i++) { - options += optionsSpecific[i]; - if (i < optionsSpecific.length - 1) { - options += ", " - } - } - options += '}}' - } - if (this.constants.smoothCurves.enabled != this.backupConstants.smoothCurves.enabled) { - if (optionsSpecific.length == 0) {options = "var options = {";} - else {options += ", "} - options += "smoothCurves: " + this.constants.smoothCurves.enabled; - } - if (options != "No options are required, default values used.") { - options += '};' - } - } - else if (radioButton2.checked == true) { - options = "var options = {"; - options += "physics: {barnesHut: {enabled: false}"; - if (this.constants.physics.repulsion.nodeDistance != this.backupConstants.physics.repulsion.nodeDistance) {optionsSpecific.push("nodeDistance: " + this.constants.physics.repulsion.nodeDistance);} - if (this.constants.physics.centralGravity != this.backupConstants.physics.repulsion.centralGravity) {optionsSpecific.push("centralGravity: " + this.constants.physics.centralGravity);} - if (this.constants.physics.springLength != this.backupConstants.physics.repulsion.springLength) {optionsSpecific.push("springLength: " + this.constants.physics.springLength);} - if (this.constants.physics.springConstant != this.backupConstants.physics.repulsion.springConstant) {optionsSpecific.push("springConstant: " + this.constants.physics.springConstant);} - if (this.constants.physics.damping != this.backupConstants.physics.repulsion.damping) {optionsSpecific.push("damping: " + this.constants.physics.damping);} - if (optionsSpecific.length != 0) { - options += ", repulsion: {"; - for (var i = 0; i < optionsSpecific.length; i++) { - options += optionsSpecific[i]; - if (i < optionsSpecific.length - 1) { - options += ", " + 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(); + }); } - } - options += '}}' - } - if (optionsSpecific.length == 0) {options += "}"} - if (this.constants.smoothCurves != this.backupConstants.smoothCurves) { - options += ", smoothCurves: " + this.constants.smoothCurves; - } - options += '};' - } - else { - options = "var options = {"; - if (this.constants.physics.hierarchicalRepulsion.nodeDistance != this.backupConstants.physics.hierarchicalRepulsion.nodeDistance) {optionsSpecific.push("nodeDistance: " + this.constants.physics.hierarchicalRepulsion.nodeDistance);} - if (this.constants.physics.centralGravity != this.backupConstants.physics.hierarchicalRepulsion.centralGravity) {optionsSpecific.push("centralGravity: " + this.constants.physics.centralGravity);} - if (this.constants.physics.springLength != this.backupConstants.physics.hierarchicalRepulsion.springLength) {optionsSpecific.push("springLength: " + this.constants.physics.springLength);} - if (this.constants.physics.springConstant != this.backupConstants.physics.hierarchicalRepulsion.springConstant) {optionsSpecific.push("springConstant: " + this.constants.physics.springConstant);} - if (this.constants.physics.damping != this.backupConstants.physics.hierarchicalRepulsion.damping) {optionsSpecific.push("damping: " + this.constants.physics.damping);} - if (optionsSpecific.length != 0) { - options += "physics: {hierarchicalRepulsion: {"; - for (var i = 0; i < optionsSpecific.length; i++) { - options += optionsSpecific[i]; - if (i < optionsSpecific.length - 1) { - options += ", "; + else { + throw new Error('The function for delete does not support two arguments (data, callback)') } } - 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 += ", " - } + else { + this.edgesData.remove(selectedEdges); + this.nodesData.remove(selectedNodes); + this._unselectAll(); + this.moving = true; + this.start(); } - options += '}' } else { - options += "enabled:true}"; + alert(this.constants.locales[this.constants.locale]["deleteClusterError"]); } - options += '};' } + }; - this.optionsDiv.innerHTML = options; - } +/***/ }, +/* 68 */ +/***/ function(module, exports, __webpack_require__) { - /** - * 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"; - } - } - 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(); + var util = __webpack_require__(1); + var Hammer = __webpack_require__(19); + + exports._cleanNavigation = function() { + // clean hammer bindings + if (this.navigationHammers.existing.length != 0) { + for (var i = 0; i < this.navigationHammers.existing.length; i++) { + this.navigationHammers.existing[i].dispose(); } + this.navigationHammers.existing = []; } - 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._navigationReleaseOverload = function () {}; + + // clean up previous navigation items + if (this.navigationDivs && this.navigationDivs['wrapper'] && this.navigationDivs['wrapper'].parentNode) { + this.navigationDivs['wrapper'].parentNode.removeChild(this.navigationDivs['wrapper']); + } + }; /** - * this generates the ranges depending on the iniital values. + * 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 id - * @param map - * @param constantsVariableName + * @private */ - function showValueOfRange (id,map,constantsVariableName) { - var valueId = id + "_value"; - var rangeValue = document.getElementById(id).value; + exports._loadNavigationElements = function() { + this._cleanNavigation(); - if (Array.isArray(map)) { - 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)); - } + this.navigationDivs = {}; + var navigationDivs = ['up','down','left','right','zoomIn','zoomOut','zoomExtends']; + var navigationDivActions = ['_moveUp','_moveDown','_moveLeft','_moveRight','_zoomIn','_zoomOut','_zoomExtent']; - if (constantsVariableName == "hierarchicalLayout_direction" || - constantsVariableName == "hierarchicalLayout_levelSeparation" || - constantsVariableName == "hierarchicalLayout_nodeSpacing") { - this._setupHierarchicalLayout(); - } - this.moving = true; - this.start(); - } + this.navigationDivs['wrapper'] = document.createElement('div'); + this.frame.appendChild(this.navigationDivs['wrapper']); + + for (var i = 0; i < navigationDivs.length; i++) { + this.navigationDivs[navigationDivs[i]] = document.createElement('div'); + this.navigationDivs[navigationDivs[i]].className = 'network-navigation ' + navigationDivs[i]; + this.navigationDivs['wrapper'].appendChild(this.navigationDivs[navigationDivs[i]]); + var hammer = Hammer(this.navigationDivs[navigationDivs[i]], {prevent_default: true}); + hammer.on('touch', this[navigationDivActions[i]].bind(this)); + this.navigationHammers._new.push(hammer); + } + this._navigationReleaseOverload = this._stopMovement; + this.navigationHammers.existing = this.navigationHammers._new; + }; -/***/ }, -/* 67 */ -/***/ function(module, exports, __webpack_require__) { - function webpackContext(req) { - throw new Error("Cannot find module '" + req + "'."); - } - webpackContext.keys = function() { return []; }; - webpackContext.resolve = webpackContext; - module.exports = webpackContext; - webpackContext.id = 67; + /** + * this stops all movement induced by the navigation buttons + * + * @private + */ + exports._zoomExtent = function(event) { + this.zoomExtent({duration:700}); + event.stopPropagation(); + }; + /** + * this stops all movement induced by the navigation buttons + * + * @private + */ + exports._stopMovement = function() { + this._xStopMoving(); + this._yStopMoving(); + this._stopZoom(); + }; -/***/ }, -/* 68 */ -/***/ function(module, exports, __webpack_require__) { /** - * Calculate the forces the nodes apply on each other based on a repulsion field. - * This field is linearly approximated. + * 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._calculateNodeForces = function () { - var dx, dy, angle, distance, fx, fy, combinedClusterSize, - repulsingForce, node1, node2, i, j; + exports._moveUp = function(event) { + this.yIncrement = this.constants.keyboard.speed.y; + this.start(); // if there is no node movement, the calculation wont be done + event.preventDefault(); + }; - var nodes = this.calculationNodes; - var nodeIndices = this.calculationNodeIndices; - // approximation constants - var a_base = -2 / 3; - var b = 4 / 3; + /** + * 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 + event.preventDefault(); + }; - // 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; + /** + * 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 + event.preventDefault(); + }; + + + /** + * 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 + event.preventDefault(); + }; + + + /** + * 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 + event.preventDefault(); + }; + + + /** + * Zoom out + * @private + */ + exports._zoomOut = function(event) { + this.zoomIncrement = -this.constants.keyboard.speed.zoom; + this.start(); // if there is no node movement, the calculation wont be done + event.preventDefault(); + }; - dx = node2.x - node1.x; - dy = node2.y - node1.y; - distance = Math.sqrt(dx * dx + dy * dy); - // same condition as BarnesHut, making sure nodes are never 100% overlapping. - if (distance == 0) { - distance = 0.1*Math.random(); - dx = distance; - } + /** + * Stop zooming and unhighlight the zoom controls + * @private + */ + exports._stopZoom = function(event) { + this.zoomIncrement = 0; + event && event.preventDefault(); + }; - 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)) - } - // amplify the repulsion for clusters. - repulsingForce *= (combinedClusterSize == 0) ? 1 : 1 + combinedClusterSize * this.constants.clustering.forceAmplification; - repulsingForce = repulsingForce / Math.max(distance,0.01*minimumDistance); + /** + * Stop moving in the Y direction and unHighlight the up and down + * @private + */ + exports._yStopMoving = function(event) { + this.yIncrement = 0; + event && event.preventDefault(); + }; - fx = dx * repulsingForce; - fy = dy * repulsingForce; - node1.fx -= fx; - node1.fy -= fy; - node2.fx += fx; - node2.fy += fy; - } - } - } + /** + * Stop moving in the X direction and unHighlight left and right. + * @private + */ + exports._xStopMoving = function(event) { + this.xIncrement = 0; + event && event.preventDefault(); }; @@ -34644,579 +33835,676 @@ return /******/ (function(modules) { // webpackBootstrap /* 69 */ /***/ 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; + node.hierarchyEnumerated = false; + } + } + } + }; + /** - * Calculate the forces the nodes apply on eachother based on a repulsion field. - * This field is linearly approximated. + * This is the main function to layout the nodes in a hierarchical way. + * It checks if the node details are supplied correctly * * @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._setupHierarchicalLayout = function() { + if (this.constants.hierarchicalLayout.enabled == true && this.nodeIndices.length > 0) { + // 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; - dx = node2.x - node1.x; - dy = node2.y - node1.y; - distance = Math.sqrt(dx * dx + dy * dy); + 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) { + throw new Error("To use the hierarchical layout, nodes require either no predefined levels or levels have to be defined for all nodes."); + this.zoomExtent({duration:0},true,this.constants.clustering.enabled); + if (!this.constants.clustering.enabled) { + this.start(); + } + } + else { + // setup the system to use hierarchical method. + this._changeConstants(); - var steepness = 0.05; - if (distance < nodeDistance) { - repulsingForce = -Math.pow(steepness*distance,2) + Math.pow(steepness*nodeDistance,2); + // define levels if undefined by the users. Based on hubsize + if (undefinedLevel == true) { + if (this.constants.hierarchicalLayout.layout == "hubsize") { + this._determineLevels(hubsize); } else { - repulsingForce = 0; + this._determineLevelsDirected(false); } - // 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; } + // check the distribution of the nodes per level. + var distribution = this._getDistribution(); + + // place the nodes on the canvas. This also stablilizes the system. + this._placeNodesByHierarchy(distribution); + + // start the simulation. + this.start(); } } }; /** - * this function calculates the effects of the springs in the case of unsmooth curves. + * This function places the nodes on the canvas based on the hierarchial distribution. * + * @param {Object} distribution | obtained by the function this._getDistribution() * @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; - } - - - // forces caused by the edges, modelled as springs - for (edgeId in edges) { - if (edges.hasOwnProperty(edgeId)) { - edge = edges[edgeId]; - if (edge.connected) { - // only calculate forces if nodes are in the same sector - if (this.nodes.hasOwnProperty(edge.toId) && this.nodes.hasOwnProperty(edge.fromId)) { - edgeLength = edge.physics.springLength; - // this implies that the edges between big clusters are longer - edgeLength += (edge.to.clusterSize + edge.from.clusterSize - 2) * this.constants.clustering.edgeGrowth; - - dx = (edge.from.x - edge.to.x); - dy = (edge.from.y - edge.to.y); - distance = Math.sqrt(dx * dx + dy * dy); - - if (distance == 0) { - distance = 0.01; - } - - // the 1/distance is so the fx and fy can be calculated without sine or cosine. - springForce = this.constants.physics.springConstant * (edgeLength - distance) / distance; - - fx = dx * springForce; - fy = dy * springForce; + 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; - if (edge.to.level != edge.from.level) { - edge.to.springFx -= fx; - edge.to.springFy -= fy; - edge.from.springFx += fx; - edge.from.springFy += fy; + distribution[level].minPos += distribution[level].nodeSpacing; + } } 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 (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); } } } } - // normalize spring forces - var springForce = 1; - var springFx, springFy; - for (i = 0; i < nodeIndices.length; i++) { - var node = nodes[nodeIndices[i]]; - springFx = Math.min(springForce,Math.max(-springForce,node.springFx)); - springFy = Math.min(springForce,Math.max(-springForce,node.springFy)); - - node.fx += springFx; - node.fy += springFy; - } - - // retain energy balance - var totalFx = 0; - var totalFy = 0; - for (i = 0; i < nodeIndices.length; i++) { - var node = nodes[nodeIndices[i]]; - totalFx += node.fx; - totalFy += node.fy; - } - var correctionFx = totalFx / nodeIndices.length; - var correctionFy = totalFy / nodeIndices.length; - - for (i = 0; i < nodeIndices.length; i++) { - var node = nodes[nodeIndices[i]]; - node.fx -= correctionFx; - node.fy -= correctionFy; - } - + // stabilize the system after positioning. This function calls zoomExtent. + this._stabilize(); }; -/***/ }, -/* 70 */ -/***/ function(module, exports, __webpack_require__) { /** - * This function calculates the forces the nodes apply on eachother based on a gravitational model. - * The Barnes Hut method is used to speed up this N-body simulation. + * This function get the distribution of levels based on hubsize * + * @returns {Object} * @private */ - exports._calculateNodeForces = function() { - if (this.constants.physics.barnesHut.gravitationalConstant != 0) { - var node; - var nodes = this.calculationNodes; - var nodeIndices = this.calculationNodeIndices; - var nodeCount = nodeIndices.length; - - this._formBarnesHutTree(nodes,nodeIndices); + exports._getDistribution = function() { + var distribution = {}; + var nodeId, node, level; - var barnesHutTree = this.barnesHutTree; + // 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; + } + } - // place the nodes one by one recursively - for (var i = 0; i < nodeCount; i++) { - node = nodes[nodeIndices[i]]; - if (node.options.mass > 0) { - // starting with root is irrelevant, it never passes the BarnesHut condition - this._getForceContribution(barnesHutTree.root.children.NW,node); - this._getForceContribution(barnesHutTree.root.children.NE,node); - this._getForceContribution(barnesHutTree.root.children.SW,node); - this._getForceContribution(barnesHutTree.root.children.SE,node); + // determine the largest amount of nodes of all levels + var maxCount = 0; + for (level in distribution) { + if (distribution.hasOwnProperty(level)) { + if (maxCount < distribution[level].amount) { + maxCount = distribution[level].amount; } } } + + // set the initial position and spacing of each nodes accordingly + for (level in distribution) { + if (distribution.hasOwnProperty(level)) { + distribution[level].nodeSpacing = (maxCount + 1) * this.constants.hierarchicalLayout.nodeSpacing; + distribution[level].nodeSpacing /= (distribution[level].amount + 1); + distribution[level].minPos = distribution[level].nodeSpacing - (0.5 * (distribution[level].amount + 1) * distribution[level].nodeSpacing); + } + } + + return distribution; }; /** - * This function 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 allocates nodes in levels based on the recursive branching from the largest hubs. * - * @param parentBranch - * @param node + * @param hubsize * @private */ - exports._getForceContribution = function(parentBranch,node) { - // we get no force contribution from an empty region - if (parentBranch.childrenCount > 0) { - var dx,dy,distance; - - // get the distance from the center of mass to the node. - dx = parentBranch.centerOfMass.x - node.x; - dy = parentBranch.centerOfMass.y - node.y; - distance = Math.sqrt(dx * dx + dy * dy); + exports._determineLevels = function(hubsize) { + var nodeId, node; - // BarnesHut condition - // original condition : s/d < thetaInverted = passed === d/s > 1/theta = passed - // calcSize = 1/s --> d * 1/s > 1/theta = passed - if (distance * parentBranch.calcSize > this.constants.physics.barnesHut.thetaInverted) { - // duplicate code to reduce function calls to speed up program - if (distance == 0) { - distance = 0.1*Math.random(); - dx = distance; + // 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 gravityForce = this.constants.physics.barnesHut.gravitationalConstant * parentBranch.mass * node.options.mass / (distance * distance * distance); - var fx = dx * gravityForce; - var fy = dy * gravityForce; - node.fx += fx; - node.fy += fy; } - else { - // Did not pass the condition, go into children if available - if (parentBranch.childrenCount == 4) { - this._getForceContribution(parentBranch.children.NW,node); - this._getForceContribution(parentBranch.children.NE,node); - this._getForceContribution(parentBranch.children.SW,node); - this._getForceContribution(parentBranch.children.SE,node); - } - else { // parentBranch must have only one node, if it was empty we wouldnt be here - if (parentBranch.children.data.id != node.id) { // if it is not self - // duplicate code to reduce function calls to speed up program - if (distance == 0) { - distance = 0.5*Math.random(); - dx = distance; - } - var gravityForce = this.constants.physics.barnesHut.gravitationalConstant * parentBranch.mass * node.options.mass / (distance * distance * distance); - var fx = dx * gravityForce; - var fy = dy * gravityForce; - node.fx += fx; - node.fy += fy; - } + } + + // 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 function constructs the barnesHut tree recursively. It creates the root, splits it and starts placing the nodes. + * this function allocates nodes in levels based on the direction of the edges * - * @param nodes - * @param nodeIndices + * @param hubsize * @private */ - exports._formBarnesHutTree = function(nodes,nodeIndices) { - var node; - var nodeCount = nodeIndices.length; + exports._determineLevelsDirected = function() { + var nodeId, node, firstNode; + var minLevel = 10000; - var minX = Number.MAX_VALUE, - minY = Number.MAX_VALUE, - maxX =-Number.MAX_VALUE, - maxY =-Number.MAX_VALUE; + // set first node to source + firstNode = this.nodes[this.nodeIndices[0]]; + firstNode.level = minLevel; + this._setLevelDirected(minLevel,firstNode.edges,firstNode.id); - // get the range of the nodes - for (var i = 0; i < nodeCount; i++) { - var x = nodes[nodeIndices[i]].x; - var y = nodes[nodeIndices[i]].y; - if (nodes[nodeIndices[i]].options.mass > 0) { - if (x < minX) { minX = x; } - if (x > maxX) { maxX = x; } - if (y < minY) { minY = y; } - if (y > maxY) { maxY = y; } + // get the minimum level + for (nodeId in this.nodes) { + if (this.nodes.hasOwnProperty(nodeId)) { + node = this.nodes[nodeId]; + minLevel = node.level < minLevel ? node.level : minLevel; } } - // make the range a square - var sizeDiff = Math.abs(maxX - minX) - Math.abs(maxY - minY); // difference between X and Y - if (sizeDiff > 0) {minY -= 0.5 * sizeDiff; maxY += 0.5 * sizeDiff;} // xSize > ySize - else {minX += 0.5 * sizeDiff; maxX -= 0.5 * sizeDiff;} // xSize < ySize - - - var minimumTreeSize = 1e-5; - var rootSize = Math.max(minimumTreeSize,Math.abs(maxX - minX)); - var halfRootSize = 0.5 * rootSize; - var centerX = 0.5 * (minX + maxX), centerY = 0.5 * (minY + maxY); - - // 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]]; - if (node.options.mass > 0) { - this._placeInTree(barnesHutTree.root,node); + // subtract the minimum from the set so we have a range starting from 0 + for (nodeId in this.nodes) { + if (this.nodes.hasOwnProperty(nodeId)) { + node = this.nodes[nodeId]; + node.level -= minLevel; } } - - // make global - this.barnesHutTree = barnesHutTree }; /** - * this updates the mass of a branch. this is increased by adding a node. + * 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. * - * @param parentBranch - * @param node * @private */ - exports._updateBranchMass = function(parentBranch, node) { - var totalMass = parentBranch.mass + node.options.mass; - var totalMassInv = 1/totalMass; - - parentBranch.centerOfMass.x = parentBranch.centerOfMass.x * parentBranch.mass + node.x * node.options.mass; - parentBranch.centerOfMass.x *= totalMassInv; - - parentBranch.centerOfMass.y = parentBranch.centerOfMass.y * parentBranch.mass + node.y * node.options.mass; - parentBranch.centerOfMass.y *= totalMassInv; + 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(); - parentBranch.mass = totalMass; - var biggestSize = Math.max(Math.max(node.height,node.radius),node.width); - parentBranch.maxWidth = (parentBranch.maxWidth < biggestSize) ? biggestSize : parentBranch.maxWidth; + var config = this.constants.hierarchicalLayout; + config.levelSeparation = Math.abs(config.levelSeparation); + if (config.direction == "RL" || config.direction == "DU") { + config.levelSeparation *= -1; + } + if (config.direction == "RL" || config.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"; + } + } }; /** - * determine in which branch the node will be placed. + * 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 parentBranch - * @param node - * @param skipMassUpdate + * @param edges + * @param parentId + * @param distribution + * @param parentLevel * @private */ - exports._placeInTree = function(parentBranch,node,skipMassUpdate) { - if (skipMassUpdate != true || skipMassUpdate === undefined) { - // update the mass of the branch. - this._updateBranchMass(parentBranch,node); - } - - 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"); + 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 { // in SW - this._placeInRegion(parentBranch,node,"SW"); + else { + childNode = edges[i].to; } - } - else { // in NE or SE - if (parentBranch.children.NW.range.maxY > node.y) { // in NE - this._placeInRegion(parentBranch,node,"NE"); + + // 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 { // in SE - this._placeInRegion(parentBranch,node,"SE"); + else { + if (childNode.yFixed && childNode.level > parentLevel) { + childNode.yFixed = false; + childNode.y = distribution[childNode.level].minPos; + nodeMoved = true; + } + } + + if (nodeMoved == true) { + distribution[childNode.level].minPos += distribution[childNode.level].nodeSpacing; + if (childNode.edges.length > 1) { + this._placeBranchNodes(childNode.edges,childNode.id,distribution,childNode.level); + } } } }; /** - * actually place the node in a region (or branch) + * this function is called recursively to enumerate the barnches of the largest hubs and give each node a level. * - * @param parentBranch - * @param node - * @param region + * @param level + * @param edges + * @param parentId * @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); + 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 (childNode.edges.length > 1) { + this._setLevel(level+1, childNode.edges, childNode.id); } - break; - case 4: // place in branch - this._placeInTree(parentBranch.children[region],node); - break; + } } }; /** - * 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. + * this function is called recursively to enumerate the branched of the first node and give each node a level based on edge direction * - * @param parentBranch + * @param level + * @param edges + * @param parentId * @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; + exports._setLevelDirected = function(level, edges, parentId) { + this.nodes[parentId].hierarchyEnumerated = true; + var childNode, direction; + for (var i = 0; i < edges.length; i++) { + direction = 1; + if (edges[i].toId == parentId) { + childNode = edges[i].from; + direction = -1; + } + else { + childNode = edges[i].to; + } + if (childNode.level == -1) { + childNode.level = level + direction; + } } - parentBranch.childrenCount = 4; - parentBranch.children.data = null; - this._insertRegion(parentBranch,"NW"); - this._insertRegion(parentBranch,"NE"); - this._insertRegion(parentBranch,"SW"); - this._insertRegion(parentBranch,"SE"); - if (containedNode != null) { - this._placeInTree(parentBranch,containedNode); + for (var i = 0; i < edges.length; i++) { + if (edges[i].toId == parentId) {childNode = edges[i].from;} + else {childNode = edges[i].to;} + + if (childNode.edges.length > 1 && childNode.hierarchyEnumerated === false) { + this._setLevelDirected(childNode.level, childNode.edges, childNode.id); + } } }; /** - * This function subdivides the region into four new segments. - * Specifically, this inserts a single new segment. - * It fills the children section of the parentBranch + * Unfix nodes * - * @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; + exports._restoreNodes = function() { + for (var nodeId in this.nodes) { + if (this.nodes.hasOwnProperty(nodeId)) { + this.nodes[nodeId].xFixed = false; + this.nodes[nodeId].yFixed = false; + } } + }; - 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 - }; +/***/ }, +/* 70 */ +/***/ function(module, exports, __webpack_require__) { + + // English + exports['en'] = { + edit: 'Edit', + del: 'Delete selected', + back: 'Back', + addNode: 'Add Node', + addEdge: 'Add Edge', + editNode: 'Edit Node', + editEdge: 'Edit Edge', + addDescription: 'Click in an empty space to place a new node.', + edgeDescription: '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.', + createEdgeError: 'Cannot link edges to a cluster.', + deleteClusterError: 'Clusters cannot be deleted.' + }; + exports['en_EN'] = exports['en']; + exports['en_US'] = exports['en']; + + // Dutch + exports['nl'] = { + edit: 'Wijzigen', + del: 'Selectie verwijderen', + back: 'Terug', + addNode: 'Node toevoegen', + addEdge: 'Link toevoegen', + editNode: 'Node wijzigen', + editEdge: 'Link wijzigen', + addDescription: 'Klik op een leeg gebied om een nieuwe node te maken.', + edgeDescription: 'Klik op een node en sleep de link naar een andere node om ze te verbinden.', + editEdgeDescription: 'Klik op de verbindingspunten en sleep ze naar een node om daarmee te verbinden.', + createEdgeError: 'Kan geen link maken naar een cluster.', + deleteClusterError: 'Clusters kunnen niet worden verwijderd.' }; + exports['nl_NL'] = exports['nl']; + exports['nl_BE'] = exports['nl']; + +/***/ }, +/* 71 */ +/***/ function(module, exports, __webpack_require__) { /** - * This function is for debugging purposed, it draws the tree. - * - * @param ctx - * @param color - * @private + * Canvas shapes used by Network */ - exports._drawTree = function(ctx,color) { - if (this.barnesHutTree !== undefined) { + if (typeof CanvasRenderingContext2D !== 'undefined') { - ctx.lineWidth = 1; + /** + * Draw a circle shape + */ + CanvasRenderingContext2D.prototype.circle = function(x, y, r) { + this.beginPath(); + this.arc(x, y, r, 0, 2*Math.PI, false); + }; - this._drawBranch(this.barnesHutTree.root,ctx,color); - } - }; + /** + * 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(); - /** - * 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"; - } + 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 - 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.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(); + }; - ctx.beginPath(); - ctx.moveTo(branch.range.maxX,branch.range.minY); - ctx.lineTo(branch.range.maxX,branch.range.maxY); - ctx.stroke(); + /** + * 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(); - ctx.beginPath(); - ctx.moveTo(branch.range.maxX,branch.range.maxY); - ctx.lineTo(branch.range.minX,branch.range.maxY); - ctx.stroke(); + 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 - ctx.beginPath(); - ctx.moveTo(branch.range.minX,branch.range.maxY); - ctx.lineTo(branch.range.minX,branch.range.minY); - ctx.stroke(); + 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(); + }; - /* - if (branch.mass > 0) { - ctx.circle(branch.centerOfMass.x, branch.centerOfMass.y, 3*branch.mass); - ctx.stroke(); - } + /** + * Draw a star shape, a star with 5 points + * @param {Number} x horizontal center + * @param {Number} y vertical center + * @param {Number} r radius, half the length of the sides of the triangle */ - }; + CanvasRenderingContext2D.prototype.star = function(x, y, r) { + // http://www.html5canvastutorials.com/labs/html5-canvas-star-spinner/ + this.beginPath(); + for (var n = 0; n < 10; n++) { + var radius = (n % 2 === 0) ? r * 1.3 : r * 0.5; + this.lineTo( + x + radius * Math.sin(n * 2 * Math.PI / 10), + y - radius * Math.cos(n * 2 * Math.PI / 10) + ); + } -/***/ }, -/* 71 */ -/***/ function(module, exports, __webpack_require__) { + this.closePath(); + }; - module.exports = function(module) { - if(!module.webpackPolyfill) { - module.deprecate = function() {}; - module.paths = []; - // module.parent = undefined by default - module.children = []; - module.webpackPolyfill = 1; - } - return module; + /** + * 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); + }; + + /** + * 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); + }; + + + + /** + * 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 + + this.beginPath(); + this.moveTo(xe, ym); + + this.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); + this.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); + + this.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); + this.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); + + this.lineTo(xe, ymb); + + this.bezierCurveTo(xe, ymb + oy, xm + ox, yeb, xm, yeb); + this.bezierCurveTo(xm - ox, yeb, x, ymb + oy, x, ymb); + + this.lineTo(x, ym); + }; + + + /** + * Draw an arrow point (no line) + */ + CanvasRenderingContext2D.prototype.arrow = function(x, y, angle, length) { + // tail + var xt = x - length * Math.cos(angle); + var yt = y - length * Math.sin(angle); + + // inner tail + // TODO: allow to customize different shapes + var xi = x - length * 0.9 * Math.cos(angle); + var yi = y - length * 0.9 * Math.sin(angle); + + // 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; + } + }; + + // TODO: add diamond shape } diff --git a/dist/vis.map b/dist/vis.map index 76783fb7..a56beeae 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","Queue","Graph3d","graph3d","Camera","Filter","Point2d","Point3d","Slider","StepNumber","Timeline","Graph2d","timeline","DateUtil","DataStep","Range","stack","TimeStep","components","items","Item","BackgroundItem","BoxItem","PointItem","RangeItem","Component","CurrentTime","CustomTime","DataAxis","GraphGroup","Group","BackgroundGroup","ItemSet","Legend","LineGraph","TimeAxis","Network","network","Edge","Groups","Images","Node","Popup","dotparser","gephiParser","Graph","Error","moment","hammer","isNumber","object","Number","giveRange","min","max","total","value","scale","Math","isString","String","isDate","Date","match","ASPDateRegex","exec","isNaN","parse","isDataTable","google","visualization","DataTable","randomUUID","S4","floor","random","toString","extend","a","i","len","arguments","length","other","prop","hasOwnProperty","selectiveExtend","props","Array","isArray","selectiveDeepExtend","b","TypeError","constructor","Object","undefined","deepExtend","selectiveNotDeepExtend","indexOf","equalArray","convert","type","Boolean","valueOf","isMoment","toDate","getType","toISOString","getAbsoluteLeft","elem","getBoundingClientRect","left","window","pageXOffset","getAbsoluteTop","top","pageYOffset","addClassName","className","classes","split","push","join","removeClassName","index","splice","forEach","callback","toArray","array","updateProperty","key","addEventListener","element","action","listener","useCapture","navigator","userAgent","attachEvent","removeEventListener","detachEvent","preventDefault","event","returnValue","getTarget","target","srcElement","nodeType","parentNode","option","asBoolean","defaultValue","asNumber","asString","asSize","asElement","hexToRGB","hex","shorthandRegex","replace","r","g","result","parseInt","overrideOpacity","color","opacity","rgb","substr","RGBToHex","red","green","blue","slice","parseColor","isValidRGB","isValidHex","hsv","hexToHSV","lighterColorHSV","h","s","v","darkerColorHSV","darkerColorHex","HSVToHex","lighterColorHex","background","border","highlight","hover","RGBToHSV","minRGB","maxRGB","d","hue","saturation","cssUtil","cssText","styles","style","trim","parts","keys","map","addCssText","currentStyles","newStyles","removeCssText","removeStyles","HSVToRGB","f","q","t","isOk","test","selectiveBridgeObject","fields","referenceObject","objectTo","create","bridgeObject","mergeOptions","mergeTarget","options","enabled","binarySearchCustom","orderedItems","searchFunction","field","field2","maxIterations","iteration","low","high","middle","item","searchResult","binarySearchValue","sidePreference","prevValue","nextValue","easeInOutQuad","start","end","duration","change","easingFunctions","linear","easeInQuad","easeOutQuad","easeInCubic","easeOutCubic","easeInOutCubic","easeInQuart","easeOutQuart","easeInOutQuart","easeInQuint","easeOutQuint","easeInOutQuint","prepareElements","JSONcontainer","elementType","redundant","used","cleanupElements","removeChild","getSVGElement","svgContainer","shift","document","createElementNS","appendChild","getDOMElement","DOMContainer","insertBefore","createElement","drawPoint","x","y","group","labelObj","point","drawPoints","setAttributeNS","size","label","xOffset","yOffset","content","textContent","drawBar","width","height","rect","data","_options","_data","_fieldId","fieldId","_type","_subscribers","add","setOptions","prototype","queue","_queue","destroy","on","subscribers","subscribe","off","filter","unsubscribe","_trigger","params","senderId","concat","subscriber","addedIds","me","_addItem","columns","_getColumnNames","row","rows","getNumberOfRows","col","cols","getValue","update","updatedIds","updatedData","addOrUpdate","_updateItem","get","ids","firstType","returnType","allowedValues","itemId","_getItem","order","_sort","_filterFields","_appendRow","getIds","getDataSet","mappedItems","filteredItem","name","sort","av","bv","remove","removedId","removedIds","_remove","clear","maxField","itemField","minField","distinct","values","fieldType","count","exists","types","raw","converted","JSON","stringify","dataTable","getNumberOfColumns","getColumnId","getColumnLabel","addRow","setValue","_ids","_onEvent","apply","setData","refresh","newIds","added","removed","viewOptions","getArguments","defaultFilter","dataSet","updated","delay","Infinity","_timeout","_extended","_flushIfNeeded","flush","methods","original","method","args","fn","context","entry","clearTimeout","setTimeout","container","SyntaxError","containerElement","margin","defaultXCenter","defaultYCenter","xLabel","yLabel","zLabel","passValueFn","xValueLabel","yValueLabel","zValueLabel","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","getMouseX","clientX","targetTouches","getMouseY","clientY","Emitter","_setScale","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","obj","sortNumber","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","textAlign","textBaseline","fillText","visible","setValues","setPlayInterval","onchange","getIndex","selectValue","setOnChangeCallback","lineStyle","getLabel","getSelectedValue","from","to","prettyStep","text","xText","yText","zText","offset","xMin2d","xMax2d","gridLenX","gridLenY","textMargin","armAngle","H","S","V","R","G","B","C","Hi","X","abs","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","startMouseY","startStart","startEnd","startArmRotation","cursor","onmousemove","_onMouseMove","onmouseup","diffX","diffY","horizontalNew","verticalNew","snapAngle","snapValue","round","parameters","emit","boundingRect","mouseX","mouseY","tooltipTimeout","_hideTooltip","dataPoint","_dataPointFromXY","_showTooltip","ontouchmove","_onTouchMove","ontouchend","_onTouchEnd","delta","wheelDelta","detail","oldLength","newLength","_insideTriangle","triangle","sign","as","bs","cs","distMax","closestDataPoint","closestDist","triangle1","triangle2","distX","distY","sqrt","line","dot","dom","borderRadius","boxShadow","borderLeft","contentWidth","offsetWidth","contentHeight","offsetHeight","lineHeight","dotWidth","dotHeight","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","log","LN10","step1","pow","step2","step5","toPrecision","getStep","groups","forthArgument","defaultOptions","autoResize","orientation","maxHeight","minHeight","_create","body","domProps","emitter","bind","hiddenDates","getScale","timeAxis","toScreen","_toScreen","toGlobalScreen","_toGlobalScreen","toTime","_toTime","toGlobalTime","_toGlobalTime","range","currentTime","customTime","itemSet","itemsData","groupsData","setGroups","setItems","_redraw","Core","markDirty","refreshItems","newDataSet","initialLoad","dataRange","_getDataRange","setWindow","animate","fit","setSelection","focus","getSelection","itemData","e","getItemRange","dataset","minItem","maxStartItem","maxEndItem","linegraph","getLegend","groupId","isGroupVisible","visibility","convertHiddenOptions","repeat","dateItem","updateHiddenDates","centerContainer","totalRange","pixelTime","startDate","endDate","_d","runUntil","clone","day","dayOfYear","year","dayOffset","date","month","console","removeDuplicates","startHidden","isHidden","endHidden","rangeStart","rangeEnd","hidden","startToFront","endToFront","_applyRange","safeDates","printDates","dates","stepOverHiddenDates","timeStep","previousTime","stepInHidden","currentValue","current","newValue","switchedYear","switchedMonth","switchedDay","time","conversion","getHiddenDurationBetween","correctTimeForHidden","hiddenDuration","totalDuration","partialDuration","accumulatedHiddenDuration","getAccumulatedHiddenDuration","newTime","getHiddenDurationBefore","timeOffset","requiredDuration","previousPoint","snapAwayFromHidden","direction","correctionEnabled","minimumStep","containerHeight","customRange","alignZeros","autoScale","stepIndex","marginStart","marginEnd","deadSpace","majorSteps","minorSteps","setMinimumStep","setFirst","safeSize","minimumStepValue","orderOfMagnitude","minorStepIdx","magnitudefactor","solutionFound","stepSize","niceStart","niceEnd","roundToMinor","marginRange","rounded","hasNext","previous","decimals","exp","cnt","isMajor","now","hours","minutes","seconds","milliseconds","deltaDifference","scaleOffset","moveable","zoomable","zoomMin","zoomMax","touch","animateTimer","_onDragStart","_onDrag","_onDragEnd","_onHold","_onMouseWheel","_onTouch","_onPinch","validateDirection","getPointer","pageX","pageY","hammerUtil","byUser","_cancelAnimation","initStart","initEnd","initTime","anyChanged","dragging","done","changed","newStart","newEnd","getRange","totalHidden","previousDelta","allowDragging","gesture","deltaX","deltaY","diffRange","safeStart","safeEnd","fakeGesture","pointer","pointerDate","_pointerToDate","zoom","touches","centerDate","hiddenDurationBefore","hiddenDurationAfter","move","EPSILON","orderByStart","orderByEnd","aTime","bTime","force","iMax","axis","collidingItem","jj","collision","nostack","subgroups","newTop","subgroup","format","FORMAT","minorLabels","millisecond","second","minute","hour","weekday","majorLabels","setFormat","defaultFormat","first","setFullYear","getFullYear","setMonth","setDate","setHours","setMinutes","setSeconds","setMilliseconds","getMilliseconds","getSeconds","getMinutes","getHours","getDate","getMonth","setScale","setAutoScale","enable","stepYear","stepMonth","stepDay","stepHour","stepMinute","stepSecond","stepMillisecond","snap","getLabelMinor","getLabelMajor","getClassName","even","today","isSame","currentWeek","currentMonth","currentYear","locale","lang","toLowerCase","_isResized","resized","_previousWidth","_previousHeight","showCurrentTime","locales","parent","backgroundVertical","title","toUpperCase","substring","currentTimeTimer","setCurrentTime","getCurrentTime","showCustomTime","eventParams","Hammer","drag","prevent_default","setCustomTime","getCustomTime","stopPropagation","svg","linegraphOptions","showMinorLabels","showMajorLabels","icons","majorLinesOffset","minorLinesOffset","labelOffsetX","labelOffsetY","iconWidth","linegraphSVG","DOMelements","lines","labels","conversionFactor","minWidth","stepPixels","stepPixelsForced","zeroCrossing","lineOffset","master","svgElements","iconsRemoved","amountOfGroups","lineContainer","scrollTop","addGroup","graphOptions","updateGroup","removeGroup","hide","show","display","_redrawGroupIcons","iconHeight","iconOffset","drawIcon","_cleanupIcons","backgroundHorizontal","activeGroups","_calculateCharSize","minorLabelHeight","minorCharHeight","majorLabelHeight","majorCharHeight","minorLineWidth","minorLineHeight","majorLineWidth","majorLineHeight","_redrawLabels","_redrawTitle","amountOfSteps","stepDifference","zeroStepDifference","valueAtZero","marginStartPos","maxLabelSize","_redrawLabel","_redrawLine","titleWidth","titleCharHeight","convertValue","invertedValue","convertedValue","characterHeight","largestWidth","majorCharWidth","minorCharWidth","textMinor","createTextNode","measureCharMinor","textMajor","measureCharMajor","textTitle","measureCharTitle","titleCharWidth","groupsUsingDefaultStyles","usingDefaultStyle","zeroPosition","Line","Bar","Points","setZeroPosition","catmullRom","parametrization","alpha","SVGcontainer","path","fillPath","fillHeight","outline","shaded","barWidth","bar1Height","bar2Height","icon","yAxisOrientation","getYRange","groupData","draw","framework","subgroupIndex","subgroupOrderer","subgroupOrder","visibleItems","byStart","byEnd","checkRangedItems","inner","foreground","marker","Element","getLabelWidth","restack","_updateVisibleItems","markerHeight","lastMarkerHeight","dirty","displayed","_calculateHeight","offsetTop","offsetLeft","ii","repositionY","resetSubgroups","labelSet","setParent","orderSubgroups","_checkIfVisible","sortArray","sortField","removeFromDataSet","removeItem","startArray","endArray","oldVisibleItems","visibleItemsLookup","lowerBound","upperBound","_checkIfVisibleWithReference","initialPosByStart","_traceVisible","initialPosByEnd","repositionX","initialPos","breakCondition","isVisible","align","groupOrder","selectable","editable","updateTime","onAdd","onUpdate","onMove","onRemove","onMoving","itemOptions","itemListeners","_onAdd","_onUpdate","_onRemove","groupListeners","_onAddGroups","_onUpdateGroups","_onRemoveGroups","groupIds","selection","stackDirty","touchParams","UNGROUPED","BACKGROUND","box","_updateUngrouped","backgroundGroup","_onSelectItem","_onMultiSelectItem","_onAddItem","addCallback","Function","unselect","select","getVisibleItems","rawVisibleItems","_deselect","_orderGroups","visibleInterval","zoomed","lastVisibleInterval","lastWidth","firstGroup","_firstGroup","firstMargin","nonFirstMargin","groupMargin","groupResized","firstGroupIndex","firstGroupId","ungrouped","_getGroupId","getLabelSet","oldItemsData","getItems","_order","getGroups","_getType","_removeItem","groupOptions","oldGroupId","oldGroup","_constructByEndArray","itemFromTarget","selected","dragLeftItem","dragRightItem","initialX","itemProps","newProps","initial","groupFromTarget","_updateItemProps","_moveToGroup","changes","ctrlKey","srcEvent","shiftKey","oldSelection","newSelection","xAbs","newItem","_getItemRange","_item","itemSetFromTarget","side","iconSize","iconSpacing","textArea","scrollableHeight","drawLegendIcons","getComputedStyle","paddingTop","defaultGroup","sampling","graphHeight","barChart","handleOverlap","dataAxis","legend","abortedGraphUpdate","updateSVGheight","updateSVGheightOnResize","lastStart","COUNTER","BarGraphFunctions","yAxisLeft","yAxisRight","legendLeft","legendRight","_updateAllGroupData","_updateGroup","groupsContent","ungroupedCounter","forceGraphUpdate","_updateGraph","rangePerPixelInv","preprocessedGroupData","processedGroupData","groupRanges","changeCalled","minDate","maxDate","_getRelevantData","_applySampling","_convertXcoordinates","_getYRanges","_updateYAxis","MAX_CYCLES","_convertYcoordinates","dataContainer","guess","increment","amountOfPoints","xDistance","pointsPerPixel","ceil","sampledData","barCombinedDataLeft","barCombinedDataRight","getStackedBarYRange","minVal","maxVal","yAxisLeftUsed","yAxisRightUsed","minLeft","minRight","maxLeft","maxRight","ignore","_toggleAxisVisiblity","drawIcons","axisUsed","datapoints","xValue","yValue","extractedData","svgHeight","labelValue","majorTexts","minorTexts","lineTop","parentChanged","foregroundNextSibling","nextSibling","backgroundNextSibling","_repaintLabels","timeLabelsize","cur","prevLine","xPrev","xFirstMajorLabel","_repaintMinorText","_repaintMajorText","_repaintMajorLine","_repaintMinorLine","leftTime","leftText","widthText","arr","pop","childNodes","nodeValue","_repaintDeleteButton","anchor","deleteButton","_updateContents","template","_updateTitle","removeAttribute","_updateDataAttributes","dataAttributes","attributes","setAttribute","_updateStyle","emptyContent","baseClassName","onTop","itemSubgroup","itemSetHeight","marginLeft","maxWidth","_repaintDragLeft","_repaintDragRight","contentLeft","parentWidth","boxWidth","dragLeft","dragRight","_determineBrowserMethod","_initializeMixinLoaders","renderRefreshRate","renderTimestep","renderTime","physicsTime","runDoubleSpeed","physicsDiscreteStepsize","initializing","triggerFunctions","edit","editEdge","connect","del","customScalingFunction","nodes","mass","radiusMin","radiusMax","shape","image","fontColor","fontSize","fontFace","fontFill","fontStrokeWidth","fontStrokeColor","fontDrawThreshold","scaleFontWithValue","fontSizeMin","fontSizeMax","fontSizeMaxVisible","level","borderWidthSelected","edges","widthSelectionMultiplier","hoverWidth","labelAlignment","arrowScaleFactor","dash","gap","altLength","inheritColor","useGradients","configurePhysics","physics","barnesHut","thetaInverted","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","clusterByZoom","navigation","keyboard","speed","bindToWindow","dataManipulation","initiallyVisible","hierarchicalLayout","levelSeparation","nodeSpacing","layout","freezeForStabilization","smoothCurves","dynamic","roundness","maxVelocity","minVelocity","stabilize","stabilizationIterations","zoomExtentOnStabilize","dragNetwork","dragNodes","hideEdgesOnDrag","hideNodesOnDrag","useDefaultGroups","constants","pixelRatio","hoverObj","controlNodesActive","navigationHammers","existing","_new","animationSpeed","animationEasingFunction","animating","easingTime","sourceScale","targetScale","sourceTranslation","targetTranslation","lockedOnNodeId","lockedOnNodeOffset","touchTime","redrawRequested","images","setOnloadCallback","_requestRedraw","xIncrement","yIncrement","zoomIncrement","_loadPhysicsSystem","_loadSectorSystem","_loadClusterSystem","_loadSelectionSystem","_loadHierarchySystem","_setTranslation","freezeSimulationEnabled","cachedFunctions","startedStabilization","stabilized","draggingNodes","calculationNodes","calculationNodeIndices","nodeIndices","canvasTopLeft","canvasBottomRight","pointerPosition","areaCenter","previousScale","nodesData","edgesData","nodesListeners","_addNodes","_updateNodes","_removeNodes","edgesListeners","_addEdges","_updateEdges","_removeEdges","moving","timer","_setupHierarchicalLayout","zoomExtent","startWithClustering","keycharm","MixinLoader","Activator","browserType","requiresTimeout","_getScriptPath","scripts","getElementsByTagName","src","_getRange","specificNodes","node","minY","maxY","minX","maxX","boundingBox","nodeId","_findCenter","initialZoom","disableStart","zoomLevel","positionDefined","predefinedPosition","numberOfNodes","factor","yDistance","xZoomLevel","yZoomLevel","animation","_updateNodeIndexList","_clearNodeIndexList","idx","_unselectAll","_createManipulatorBar","dotData","DOTToGraph","gephi","gephiData","parseGephi","_setNodes","_setEdges","_putDataInSector","_resetLevels","_stabilize","onEdit","onEditEdge","onConnect","onDelete","editMode","newColorObj","groupname","clickToUse","activator","_createKeyBinds","_loadNavigationControls","_loadManipulationSystem","_configureSmoothCurves","_bindHammer","_markAllEdgesAsDirty","tabIndex","devicePixelRatio","webkitBackingStorePixelRatio","mozBackingStorePixelRatio","msBackingStorePixelRatio","oBackingStorePixelRatio","backingStorePixelRatio","setTransform","dispose","pinch","_onTap","_onDoubleTap","_onMouseMoveTitle","hammerFrame","_onRelease","reset","isActive","_moveUp","_yStopMoving","_moveDown","_moveLeft","_xStopMoving","_moveRight","_zoomIn","_stopZoom","_zoomOut","_deleteSelected","_cleanupPhysicsConfiguration","_recursiveDOMDelete","DOMobject","_getPointer","pinched","_getScale","_handleTouch","_handleDragStart","_getNodeAt","_getTranslation","isSelected","_selectObject","nodeIds","objectId","selectionObj","xFixed","yFixed","_handleOnDrag","releaseNode","_XconvertDOMtoCanvas","_XconvertCanvasToDOM","_YconvertDOMtoCanvas","_YconvertCanvasToDOM","_handleDragEnd","_handleTap","_handleDoubleTap","_handleOnHold","_handleOnRelease","_zoom","scaleOld","preScaleDragPointer","DOMtoCanvas","scaleFrac","tx","ty","updateClustersDefault","postScaleDragPointer","canvasToDOM","popupVisible","popup","_checkHidePopup","setPosition","checkShow","_checkShowPopup","popupTimer","edgeId","_getEdgeAt","_hoverObject","_blurObject","previousPopupObjId","popupObj","nodeUnderCursor","popupType","overlappingNodes","isOverlappingWith","getTitle","overlappingEdges","edge","connected","popupTargetType","popupTargetId","setText","pointerObj","stillOnObj","overNode","emitEvent","oldWidth","oldHeight","oldNodesData","_updateSelection","angle","_updateCalculationNodes","_reconnectEdges","_updateValueRange","updateLabels","changedData","setProperties","properties","colorDirty","_removeFromSelection","oldEdgesData","oldEdge","disconnect","showInternalIds","_createBezierNodes","via","sectors","dynamicEdges","valueTotal","setValueRange","requestAnimationFrame","w","save","translate","_doInAllSectors","restore","offsetX","offsetY","_drawNodes","alwaysShow","setScaleAndPos","inArea","sMax","_drawEdges","_drawControlNodes","_freezeDefinedNodes","_physicsTick","_restoreFrozenNodes","fixedData","_isMoving","vmin","isMoving","_discreteStepNodes","nodesPresent","discreteStepLimited","discreteStep","vminCorrected","_revertPhysicsState","revertPosition","_revertPhysicsTick","_doInAllActiveSectors","_doInSupportSector","mainMovingStatus","supportMovingStatus","mainMoving","_animationStep","_handleNavigation","startTime","renderStartTime","mozRequestAnimationFrame","webkitRequestAnimationFrame","msRequestAnimationFrame","iterations","freezeSimulation","freeze","parentEdgeId","internalMultiplier","positionBezierNode","mixin","storePosition","storePositions","dataArray","allowedToMoveX","allowedToMoveY","getPositions","focusOnNode","nodePosition","lockedOnNode","easingFunction","animateView","locked","_transitionRedraw","viewCenter","distanceFromCenter","_classicRedraw","_lockedRedraw","active","getCenterCoordinates","getBoundingBox","getConnectedNodes","nodeList","nodeObj","toId","fromId","getEdgesFromNode","edgesList","generateColorObject","networkConstants","widthSelected","labelDimensions","yLine","dirtyLabel","fromBackup","toBackup","originalFromId","originalToId","widthFixed","lengthFixed","controlNodesEnabled","controlNodes","positions","connectedNode","_drawLine","_drawArrow","_drawArrowCenter","_drawDashLine","attachEdge","detachEdge","widthDiff","xFrom","yFrom","xTo","yTo","xObj","yObj","_getDistanceToEdge","_getColor","colorObj","fromColor","toColor","grd","createLinearGradient","addColorStop","_getLineWidth","_line","midpointX","midpointY","_pointOnLine","_label","resize","_circle","_pointOnCircle","networkScaleInv","_getViaCoordinates","xVia","yVia","pi","originalAngle","atan2","myAngle","quadraticCurveTo","lineCount","measureText","_rotateForLabelAlignment","_drawLabelRect","_drawLabelText","angleInDegrees","rotate","lineMargin","fillRect","lineJoin","strokeText","setLineDash","pattern","lineDashOffset","lineCap","dashedLine","percentage","arrow","_pointOnBezier","_findBorderPosition","distanceToBorder","distanceToNodes","difference","threshold","arrowPos","guidePos","edgeSegmentLength","toBorderDist","toBorderPoint","x1","y1","x2","y2","x3","y3","lastX","lastY","minDistance","_getDistanceToLine","px","py","something","u","nodeIdFrom","nodeIdTo","getControlNodeFromPosition","getControlNodeToPosition","_enableControlNodes","_disableControlNodes","_getSelectedControlNode","fromDistance","toDistance","_restoreControlNodes","controlnodeFromPos","fromBorderDist","fromBorderPoint","controlnodeToPos","defaultIndex","groupsArray","groupIndex","DEFAULT","groupName","imageBroken","load","url","brokenUrl","img","Image","onload","onerror","error","imagelist","grouplist","reroutedEdges","horizontalAlignLeft","verticalAlignTop","baseRadiusValue","radiusFixed","preassignedLevel","hierarchyEnumerated","fx","fy","vx","vy","previousState","resetCluster","clusterSession","clusterSizeWidthFactor","clusterSizeHeightFactor","clusterSizeRadiusFactor","growthIndicator","networkScale","formationScale","clusterSize","containedNodes","containedEdges","clusterSessions","originalLabel","triggerFunction","groupObj","imageObj","brokenImage","_drawDatabase","_resizeDatabase","_drawBox","_resizeBox","_drawCircle","_resizeCircle","_drawEllipse","_resizeEllipse","_drawImage","_resizeImage","_drawCircularImage","_resizeCircularImage","_drawText","_resizeText","_drawDot","_resizeShape","_drawSquare","_drawTriangle","_drawTriangleDown","_drawStar","_drawIcon","_resizeIcon","_reset","clearSizeCache","_setForce","_addForce","storeState","isFixed","velocity","getDistance","radiusDiff","fontDiff","_drawImageAtPosition","globalAlpha","drawImage","_drawImageLabel","getTextSize","_swapToImageResizeWhenImageLoaded","diameter","centerX","centerY","_drawRawCircle","circle","clip","textSize","clusterLineWidth","selectionLineWidth","roundRect","database","defaultSize","ellipse","_drawShape","radiusMultiplier","_icon","iconTextSpacing","relativeIconSize","iconFontFace","iconColor","baseline","labelUnderNode","relativeFontSize","strokecolor","inView","clearVelocity","updateVelocity","massBeforeClustering","energyBefore","fontFamily","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","graphData","dotNode","graphNode","convertEdge","dotEdge","graphEdge","subEdge","{","}","[","]",";","=",",","->","--","gephiJSON","allowedToMove","gEdges","gNodes","gEdge","source","gNode","leftContainer","rightContainer","shadowTop","shadowBottom","shadowTopLeft","shadowBottomLeft","shadowTopRight","shadowBottomRight","_redrawTimer","listeners","events","scrollTopMin","redrawCount","_initAutoResize","component","_stopAutoResize","what","getWindow","borderRootHeight","borderRootWidth","autoHeight","centerWidth","_updateScrollTop","visibilityTop","visibilityBottom","MAX_REDRAWS","repaint","_startAutoResize","_onResize","lastHeight","watchTimer","setInterval","initialScrollTop","oldScrollTop","_getScrollTop","newScrollTop","_setScrollTop","eventType","getTouchList","collectEventData","custom","back","editNode","addDescription","edgeDescription","editEdgeDescription","createEdgeError","deleteClusterError","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","Bargraph","barCombinedData","coreDistance","drawData","combinedData","intersections","barPoints","_getDataIntersections","heightOffset","_getSafeDrawData","nextKey","amount","resolved","prevKey","accumulated","groupLabel","_getStackedBarYRange","xpos","_catmullRom","_linear","dFill","_catmullRomUniform","p0","p1","p2","p3","bp1","bp2","normalization","d1","d2","d3","A","N","M","d3powA","d2powA","d3pow2A","d2pow2A","d1pow2A","d1powA","PhysicsMixin","ClusterMixin","SectorsMixin","SelectionMixin","ManipulationMixin","NavigationMixin","HierarchicalLayoutMixin","_loadMixin","sourceVariable","mixinFunction","_clearMixin","_loadSelectedForceSolver","_loadPhysicsConfiguration","hubThreshold","activeSector","drawingNode","blockConnectingEdgeSelection","forceAppendSelection","manipulationDiv","editModeDiv","closeDiv","_cleanNavigation","_loadNavigationElements","overlay","_onTapOverlay","windowHammer","_hasParent","deactivate","escListener","activate","unbind","_callbacks","once","self","removeListener","removeAllListeners","callbacks","cb","hasListeners","__WEBPACK_AMD_DEFINE_RESULT__","setup","READY","Event","determineEventTypes","Utils","each","gestures","Detection","register","onTouch","DOCUMENT","EVENT_MOVE","detect","EVENT_END","Instance","VERSION","defaults","behavior","userSelect","touchAction","touchCallout","contentZooming","userDrag","tapHighlightColor","HAS_POINTEREVENTS","pointerEnabled","msPointerEnabled","HAS_TOUCHEVENTS","IS_MOBILE","NO_MOUSEEVENTS","CALCULATE_INTERVAL","EVENT_TYPES","DIRECTION_DOWN","DIRECTION_LEFT","DIRECTION_UP","DIRECTION_RIGHT","POINTER_MOUSE","POINTER_TOUCH","POINTER_PEN","EVENT_START","EVENT_RELEASE","EVENT_TOUCH","plugins","utils","dest","handler","iterator","inStr","find","inArray","hasParent","getCenter","getVelocity","deltaTime","getAngle","touch1","touch2","getDirection","getRotation","isVertical","setPrefixedCss","toggle","prefixes","toCamelCase","toggleBehavior","falseFn","onselectstart","ondragstart","str","preventMouseEvents","started","shouldDetect","hook","onTouchHandler","ev","triggerType","srcType","isPointer","isMouse","buttons","PointerEvent","matchType","updatePointer","doDetect","touchList","touchListLength","triggerChange","trigger","changedLength","changedTouches","evData","identifiers","identifier","pointerType","timeStamp","preventManipulation","stopDetect","pointers","touchlist","pointerEvent","pointerId","pt","MSPOINTER_TYPE_MOUSE","MSPOINTER_TYPE_TOUCH","MSPOINTER_TYPE_PEN","detection","stopped","startDetect","inst","eventData","startEvent","lastEvent","lastCalcEvent","futureCalcEvent","lastCalcData","extendEventData","instOptions","getCalculatedData","recalc","calcEv","calcData","velocityX","velocityY","interimAngle","interimDirection","startEv","lastEv","rotation","eventStartHandler","eventHandlers","createEvent","initEvent","dispatchEvent","state","eh","dragGesture","dragMaxTouches","triggered","dragMinDistance","startCenter","dragDistanceCorrection","dragLockToAxis","dragLockMinDistance","lastDirection","dragBlockVertical","dragBlockHorizontal","Drag","Gesture","holdGesture","holdTimeout","holdThreshold","Hold","Release","Swipe","swipeMinTouches","swipeMaxTouches","swipeVelocityX","swipeVelocityY","tapGesture","sincePrev","didDoubleTap","hasMoved","tapMaxDistance","tapMaxTime","doubleTapInterval","doubleTapDistance","tapAlways","Tap","Touch","preventMouse","transformGesture","scaleThreshold","rotationThreshold","transformMinScale","transformMinRotation","Transform","__WEBPACK_AMD_DEFINE_FACTORY__","__WEBPACK_AMD_DEFINE_ARRAY__","_exportFunctions","_bound","keydown","keyup","_keys","fromCharCode","code","down","handleEvent","up","keyCode","bound","bindAll","getKey","newBindings","global","dfl","hasOwnProp","defaultParsingFlags","empty","unusedTokens","unusedInput","charsLeftOver","nullInput","invalidMonth","invalidFormat","userInvalidated","iso","printMsg","msg","suppressDeprecationWarnings","warn","deprecate","firstTime","deprecateSimple","deprecations","padToken","func","leftZeroFill","ordinalizeToken","period","localeData","ordinal","monthDiff","anchor2","adjust","wholeMonthDiff","meridiemFixWrap","meridiem","isPm","meridiemHour","isPM","Locale","Moment","config","skipOverflow","checkOverflow","copyConfig","updateInProgress","updateOffset","Duration","normalizedInput","normalizeObjectUnits","years","quarters","quarter","months","weeks","week","days","_milliseconds","_days","_months","_locale","_bubble","val","_isAMomentObject","_i","_f","_l","_strict","_tzm","_isUTC","_offset","_pf","momentProperties","absRound","number","targetLength","forceSign","output","positiveMomentsDifference","base","res","isAfter","momentsDifference","makeAs","isBefore","createAdder","dur","tmp","addOrSubtractDurationFromMoment","mom","isAdding","setTime","rawSetter","rawGetter","rawMonthSetter","input","compareArrays","dontConvert","lengthDiff","diffs","toInt","normalizeUnits","units","lowered","unitAliases","camelFunctions","inputObject","normalizedProp","makeList","setter","getter","results","utc","set","argumentForCoercion","coercedNumber","isFinite","daysInMonth","UTC","getUTCDate","weeksInYear","dow","doy","weekOfYear","daysInYear","isLeapYear","_a","MONTH","DATE","YEAR","HOUR","MINUTE","SECOND","MILLISECOND","_overflowDayOfYear","isValid","_isValid","getTime","bigHour","normalizeLocale","chooseLocale","names","loadLocale","oldLocale","hasModule","model","local","removeFormattingTokens","makeFormatFunction","formattingTokens","formatTokenFunctions","formatMoment","expandFormat","formatFunctions","invalidDate","replaceLongDateFormatTokens","longDateFormat","localFormattingTokens","lastIndex","getParseRegexForToken","parseTokenOneDigit","parseTokenThreeDigits","parseTokenFourDigits","parseTokenOneToFourDigits","parseTokenSignedNumber","parseTokenSixDigits","parseTokenOneToSixDigits","parseTokenTwoDigits","parseTokenOneToThreeDigits","parseTokenWord","_meridiemParse","parseTokenOffsetMs","parseTokenTimestampMs","parseTokenTimezone","parseTokenT","parseTokenDigits","parseTokenOneOrTwoDigits","_ordinalParse","_ordinalParseLenient","RegExp","regexpEscape","unescapeFormat","utcOffsetFromString","string","possibleTzMatches","tzChunk","parseTimezoneChunker","addTimeToArrayFromToken","datePartArray","monthsParse","_dayOfYear","parseTwoDigitYear","_meridiem","_useUTC","weekdaysParse","_w","invalidWeekday","dayOfYearFromWeekInfo","weekYear","temp","GG","W","E","_week","gg","dayOfYearFromWeeks","dateFromConfig","currentDate","yearToUse","currentDateArray","makeUTCDate","getUTCMonth","_nextDay","makeDate","setUTCMinutes","getUTCMinutes","dateFromObject","getUTCFullYear","makeDateFromStringAndFormat","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","substituteTimeAgo","withoutSuffix","isFuture","relativeTime","posNegDuration","relativeTimeThresholds","firstDayOfWeek","firstDayOfWeekOfYear","adjustedMoment","daysToDayOfWeek","daysToAdd","getUTCDay","makeMoment","invalid","preparse","pickBy","moments","dayOfMonth","unit","makeAccessor","keepTime","daysToYears","yearsToDays","makeDurationGetter","makeGlobal","shouldDeprecate","ender","oldGlobalMoment","globalScope","aspNetTimeSpanJsonRegex","isoDurationRegex","isoFormat","unitMillisecondFactors","Milliseconds","Seconds","Minutes","Hours","Days","Months","Years","D","Q","DDD","dayofyear","isoweekday","isoweek","weekyear","isoweekyear","ordinalizeTokens","paddedTokens","MMM","monthsShort","MMMM","dd","weekdaysMin","ddd","weekdaysShort","dddd","weekdays","isoWeek","YY","YYYY","YYYYY","YYYYYY","gggg","ggggg","isoWeekYear","GGGG","GGGGG","isoWeekday","SS","SSS","SSSS","Z","utcOffset","ZZ","zoneAbbr","zz","zoneName","unix","lists","DDDD","_monthsShort","monthName","regex","_monthsParse","_longMonthsParse","_shortMonthsParse","_weekdays","_weekdaysShort","_weekdaysMin","weekdayName","_weekdaysParse","_longDateFormat","LTS","LT","L","LL","LLL","LLLL","isLower","_calendar","sameDay","nextDay","nextWeek","lastDay","lastWeek","sameElse","calendar","_relativeTime","future","past","mm","hh","MM","yy","pastFuture","_ordinal","postformat","firstDayOfYear","_invalidDate","ret","parseIso","diffRes","isDuration","inp","version","relativeTimeThreshold","limit","defineLocale","_abbr","abbr","langData","flags","parseZone","isDSTShifted","parsingFlags","invalidAt","keepLocalTime","_dateUtcOffset","inputString","asFloat","that","zoneDiff","humanize","fromNow","sod","startOf","isDST","getDay","endOf","inputMs","isBetween","zone","localAdjust","_changeInProgress","isLocal","isUtcOffset","isUtc","hasAlignedHourOffset","isoWeeksInYear","weekInfo","newLocaleData","getTimezoneOffset","isoWeeks","toJSON","isUTC","withSuffix","toIsoString","asSeconds","asMilliseconds","asMinutes","asHours","asDays","asWeeks","asMonths","asYears","ordinalParse","require","noGlobal","clusterToFit","maxNumberOfNodes","reposition","maxLevels","forceAggregateHubs","normalizeClusterLevels","increaseClusterLevel","repositionNodes","openCluster","isMovingBeforeClustering","_nodeInActiveArea","_sector","_addSector","decreaseClusterLevel","_expandClusterNode","updateClusters","zoomDirection","recursive","doNotStart","amountOfNodes","detectedZoomingIn","detectedZoomingOut","_collapseSector","_formClusters","_openClusters","_aggregateHubs","handleChains","chainPercentage","_getChainFraction","_reduceAmountOfChains","_getHubSize","_formClustersByHub","_openClustersBySize","openAll","containedNodeId","childNode","_expelChildFromParent","_releaseContainedEdges","_connectEdgeBackToChild","_validateEdges","othersPresent","childNodeId","_repositionBezierNodes","_formClustersByZoom","_forceClustersByZoom","minLength","_addToCluster","_clusterToSmallestNeighbour","smallestNeighbour","smallestNeighbourNode","neighbour","onlyEqual","_formClusterFromHub","hubNode","absorptionSizeOffset","allowCluster","edgesIdarray","amountOfInitialEdges","children","childrenIds","_addToContainedEdges","_connectEdgeToCluster","_containCircularEdgesFromNode","massBefore","_addToReroutedEdges","maxLevel","minLevel","clusterLevel","targetLevel","average","averageSquared","hubCounter","largestHub","variance","standardDeviation","fraction","reduceAmount","chains","_switchToSector","sectorId","sectorType","_switchToActiveSector","_switchToFrozenSector","_switchToSupportSector","_loadLatestSector","_previousSector","_setActiveSector","newId","_forgetLastSector","_createNewSector","_deleteActiveSector","_deleteFrozenSector","_freezeSector","_activateSector","_mergeThisWithFrozen","_collapseThisToSingleCluster","sector","unqiueIdentifier","previousSector","runFunction","argument","returnValues","_doInAllFrozenSectors","_drawSectorNodes","_drawAllSectorNodes","_getNodesOverlappingWith","_getAllNodesOverlappingWith","_pointerToPositionObject","positionObject","_getEdgesOverlappingWith","_getAllEdgesOverlappingWith","_addToSelection","_addToHover","doNotTrigger","_unselectClusters","_getSelectedNodeCount","_getSelectedNode","_getSelectedEdge","_getSelectedEdgeCount","_getSelectedObjectCount","_selectionIsEmpty","_clusterInSelection","_selectConnectedEdges","_hoverConnectedEdges","_unselectConnectedEdges","append","highlightEdges","overrideSelectable","DOM","_manipulationReleaseOverload","_navigationReleaseOverload","getSelectedNodes","edgeIds","getSelectedEdges","idArray","selectNodes","RangeError","selectEdges","_clearManipulatorBar","manipulationDOM","_restoreOverloadedFunctions","functionName","_toggleEditMode","toolbar","boundFunction","edgeBeingEdited","selectedControlNode","_createAddNodeToolbar","_createAddEdgeToolbar","_editNode","_createEditEdgeToolbar","_addNode","_handleConnect","_finishConnect","_selectControlNode","_controlNodeDrag","_releaseControlNode","newNode","_editEdge","alert","supportNodes","targetNode","connectionEdge","connectFromId","_createEdge","defaultData","finalizedData","sourceNodeId","targetNodeId","selectedNodes","selectedEdges","navigationDivs","navigationDivActions","_stopMovement","_zoomExtent","hubsize","definedLevel","undefinedLevel","_changeConstants","_determineLevels","_determineLevelsDirected","distribution","_getDistribution","_placeNodesByHierarchy","minPos","_placeBranchNodes","maxCount","_setLevel","firstNode","_setLevelDirected","parentId","parentLevel","nodeMoved","_restoreNodes","graphToggleSmoothCurves","graph_toggleSmooth","getElementById","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","supportNodeId","gravity","gravityForce","edgeLength","springForce","combinedClusterSize","node1","node2","node3","_calculateSpringForce","physicsConfiguration","maxGravitational","maxSpring","hierarchicalLayoutDirections","parentElement","rangeElement","radioButton3","graph_repositionNodes","graph_generateOptions","dynamicSmoothCurves","nameArray","webpackContext","req","resolve","repulsingForce","a_base","minimumDistance","steepness","springFx","springFy","totalFx","totalFy","correctionFx","correctionFy","nodeCount","_formBarnesHutTree","_getForceContribution","NW","NE","SW","SE","parentBranch","childrenCount","centerOfMass","calcSize","MAX_VALUE","sizeDiff","minimumTreeSize","rootSize","halfRootSize","_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","Queue","Graph3d","graph3d","Camera","Filter","Point2d","Point3d","Slider","StepNumber","Timeline","Graph2d","timeline","DateUtil","DataStep","Range","stack","TimeStep","components","items","Item","BackgroundItem","BoxItem","PointItem","RangeItem","Component","CurrentTime","CustomTime","DataAxis","GraphGroup","Group","BackgroundGroup","ItemSet","Legend","LineGraph","TimeAxis","Network","network","Edge","Groups","Images","Node","Popup","dotparser","gephiParser","Graph","Error","moment","hammer","isNumber","object","Number","giveRange","min","max","total","value","scale","Math","isString","String","isDate","Date","match","ASPDateRegex","exec","isNaN","parse","isDataTable","google","visualization","DataTable","randomUUID","S4","floor","random","toString","extend","a","i","len","arguments","length","other","prop","hasOwnProperty","selectiveExtend","props","Array","isArray","selectiveDeepExtend","b","TypeError","constructor","Object","undefined","deepExtend","selectiveNotDeepExtend","indexOf","equalArray","convert","type","Boolean","valueOf","isMoment","toDate","getType","toISOString","getAbsoluteLeft","elem","getBoundingClientRect","left","window","pageXOffset","getAbsoluteTop","top","pageYOffset","addClassName","className","classes","split","push","join","removeClassName","index","splice","forEach","callback","toArray","array","updateProperty","key","addEventListener","element","action","listener","useCapture","navigator","userAgent","attachEvent","removeEventListener","detachEvent","preventDefault","event","returnValue","getTarget","target","srcElement","nodeType","parentNode","option","asBoolean","defaultValue","asNumber","asString","asSize","asElement","hexToRGB","hex","shorthandRegex","replace","r","g","result","parseInt","overrideOpacity","color","opacity","rgb","substr","RGBToHex","red","green","blue","slice","parseColor","isValidRGB","isValidHex","hsv","hexToHSV","lighterColorHSV","h","s","v","darkerColorHSV","darkerColorHex","HSVToHex","lighterColorHex","background","border","highlight","hover","RGBToHSV","minRGB","maxRGB","d","hue","saturation","cssUtil","cssText","styles","style","trim","parts","keys","map","addCssText","currentStyles","newStyles","removeCssText","removeStyles","HSVToRGB","f","q","t","isOk","test","selectiveBridgeObject","fields","referenceObject","objectTo","create","bridgeObject","mergeOptions","mergeTarget","options","enabled","binarySearchCustom","orderedItems","searchFunction","field","field2","maxIterations","iteration","low","high","middle","item","searchResult","binarySearchValue","sidePreference","prevValue","nextValue","easeInOutQuad","start","end","duration","change","easingFunctions","linear","easeInQuad","easeOutQuad","easeInCubic","easeOutCubic","easeInOutCubic","easeInQuart","easeOutQuart","easeInOutQuart","easeInQuint","easeOutQuint","easeInOutQuint","__WEBPACK_AMD_DEFINE_RESULT__","global","dfl","hasOwnProp","defaultParsingFlags","empty","unusedTokens","unusedInput","overflow","charsLeftOver","nullInput","invalidMonth","invalidFormat","userInvalidated","iso","printMsg","msg","suppressDeprecationWarnings","console","warn","deprecate","fn","firstTime","apply","deprecateSimple","name","deprecations","padToken","func","count","leftZeroFill","ordinalizeToken","period","localeData","ordinal","monthDiff","anchor2","adjust","wholeMonthDiff","year","month","anchor","clone","add","meridiemFixWrap","locale","hour","meridiem","isPm","meridiemHour","isPM","Locale","Moment","config","skipOverflow","checkOverflow","copyConfig","_d","updateInProgress","updateOffset","Duration","normalizedInput","normalizeObjectUnits","years","quarters","quarter","months","weeks","week","days","day","hours","minutes","minute","seconds","second","milliseconds","millisecond","_milliseconds","_days","_months","_data","_locale","_bubble","to","from","val","_isAMomentObject","_i","_f","_l","_strict","_tzm","_isUTC","_offset","_pf","momentProperties","absRound","number","ceil","targetLength","forceSign","output","abs","sign","positiveMomentsDifference","base","res","isAfter","momentsDifference","makeAs","isBefore","createAdder","direction","dur","tmp","addOrSubtractDurationFromMoment","mom","isAdding","setTime","rawSetter","rawGetter","rawMonthSetter","input","prototype","compareArrays","array1","array2","dontConvert","lengthDiff","diffs","toInt","normalizeUnits","units","lowered","toLowerCase","unitAliases","camelFunctions","inputObject","normalizedProp","makeList","setter","format","getter","method","results","utc","set","argumentForCoercion","coercedNumber","isFinite","daysInMonth","UTC","getUTCDate","weeksInYear","dow","doy","weekOfYear","daysInYear","isLeapYear","_a","MONTH","DATE","YEAR","HOUR","MINUTE","SECOND","MILLISECOND","_overflowDayOfYear","isValid","_isValid","getTime","bigHour","normalizeLocale","chooseLocale","names","j","next","loadLocale","oldLocale","locales","hasModule","e","code","model","diff","local","removeFormattingTokens","makeFormatFunction","formattingTokens","formatTokenFunctions","Function","formatMoment","expandFormat","formatFunctions","invalidDate","replaceLongDateFormatTokens","longDateFormat","localFormattingTokens","lastIndex","getParseRegexForToken","token","strict","parseTokenOneDigit","parseTokenThreeDigits","parseTokenFourDigits","parseTokenOneToFourDigits","parseTokenSignedNumber","parseTokenSixDigits","parseTokenOneToSixDigits","parseTokenTwoDigits","parseTokenOneToThreeDigits","parseTokenWord","_meridiemParse","parseTokenOffsetMs","parseTokenTimestampMs","parseTokenTimezone","parseTokenT","parseTokenDigits","parseTokenOneOrTwoDigits","_ordinalParse","_ordinalParseLenient","RegExp","regexpEscape","unescapeFormat","utcOffsetFromString","string","possibleTzMatches","tzChunk","parseTimezoneChunker","addTimeToArrayFromToken","datePartArray","monthsParse","_dayOfYear","parseTwoDigitYear","_meridiem","parseFloat","_useUTC","weekdaysParse","_w","invalidWeekday","dayOfYearFromWeekInfo","w","weekYear","weekday","temp","GG","W","E","_week","gg","dayOfYearFromWeeks","dayOfYear","dateFromConfig","date","currentDate","yearToUse","currentDateArray","makeUTCDate","getUTCMonth","_nextDay","makeDate","setUTCMinutes","getUTCMinutes","dateFromObject","now","getUTCFullYear","getFullYear","getMonth","getDate","makeDateFromStringAndFormat","ISO_8601","parseISO","parsedInput","tokens","skipped","stringLength","totalParsedInputLength","matched","p1","p2","p3","p4","makeDateFromStringAndArray","tempConfig","bestMoment","scoreToBeat","currentScore","NaN","score","l","isoRegex","isoDates","isoTimes","makeDateFromString","createFromInputFallback","arr","makeDateFromInput","aspNetJsonRegex","obj","y","M","ms","setFullYear","setUTCFullYear","parseWeekday","substituteTimeAgo","withoutSuffix","isFuture","relativeTime","posNegDuration","round","as","args","relativeTimeThresholds","firstDayOfWeek","firstDayOfWeekOfYear","adjustedMoment","daysToDayOfWeek","daysToAdd","getUTCDay","makeMoment","invalid","preparse","pickBy","moments","dayOfMonth","unit","makeAccessor","keepTime","daysToYears","yearsToDays","makeDurationGetter","makeGlobal","shouldDeprecate","ender","oldGlobalMoment","globalScope","VERSION","aspNetTimeSpanJsonRegex","isoDurationRegex","isoFormat","unitMillisecondFactors","Milliseconds","Seconds","Minutes","Hours","Days","Months","Years","D","Q","DDD","dayofyear","isoweekday","isoweek","weekyear","isoweekyear","ordinalizeTokens","paddedTokens","MMM","monthsShort","MMMM","dd","weekdaysMin","ddd","weekdaysShort","dddd","weekdays","isoWeek","YY","YYYY","YYYYY","YYYYYY","gggg","ggggg","isoWeekYear","GGGG","GGGGG","isoWeekday","A","H","S","SS","SSS","SSSS","Z","utcOffset","ZZ","z","zoneAbbr","zz","zoneName","x","X","unix","lists","pop","DDDD","source","_monthsShort","monthName","regex","_monthsParse","_longMonthsParse","_shortMonthsParse","_weekdays","_weekdaysShort","_weekdaysMin","weekdayName","_weekdaysParse","_longDateFormat","LTS","LT","L","LL","LLL","LLLL","toUpperCase","charAt","isLower","_calendar","sameDay","nextDay","nextWeek","lastDay","lastWeek","sameElse","calendar","_relativeTime","future","past","mm","hh","MM","yy","pastFuture","_ordinal","postformat","firstDayOfYear","_invalidDate","ret","parseIso","diffRes","isDuration","inp","version","defaultFormat","relativeTimeThreshold","threshold","limit","lang","values","data","defineLocale","_abbr","abbr","langData","flags","parseZone","isDSTShifted","parsingFlags","invalidAt","keepLocalTime","subtract","_dateUtcOffset","inputString","asFloat","that","zoneDiff","time","humanize","fromNow","sod","startOf","isDST","getDay","endOf","inputMs","isBetween","isSame","zone","localAdjust","offset","_changeInProgress","isLocal","isUtcOffset","isUtc","hasAlignedHourOffset","isoWeeksInYear","weekInfo","get","newLocaleData","getTimezoneOffset","dates","isoWeeks","toJSON","isUTC","withSuffix","toIsoString","asSeconds","asMilliseconds","asMinutes","asHours","asDays","asWeeks","asMonths","asYears","ordinalParse","require","noGlobal","webpackContext","req","resolve","webpackPolyfill","paths","children","prepareElements","JSONcontainer","elementType","redundant","used","cleanupElements","removeChild","getSVGElement","svgContainer","shift","document","createElementNS","appendChild","getDOMElement","DOMContainer","insertBefore","createElement","drawPoint","group","labelObj","point","drawPoints","setAttributeNS","size","label","xOffset","yOffset","content","textContent","drawBar","width","height","rect","_options","_fieldId","fieldId","_type","_subscribers","setOptions","queue","_queue","destroy","on","subscribers","subscribe","off","filter","unsubscribe","_trigger","params","senderId","concat","subscriber","addedIds","me","_addItem","columns","_getColumnNames","row","rows","getNumberOfRows","col","cols","getValue","update","updatedIds","updatedData","addOrUpdate","_updateItem","ids","firstType","returnType","allowedValues","itemId","_getItem","order","_sort","_filterFields","_appendRow","getIds","getDataSet","mappedItems","filteredItem","sort","av","bv","remove","removedId","removedIds","_remove","clear","maxField","itemField","minField","distinct","fieldType","exists","types","raw","converted","JSON","stringify","dataTable","getNumberOfColumns","getColumnId","getColumnLabel","addRow","setValue","delay","Infinity","_timeout","_extended","_flushIfNeeded","flush","methods","original","context","entry","clearTimeout","setTimeout","_ids","_onEvent","setData","refresh","newIds","added","removed","viewOptions","getArguments","defaultFilter","dataSet","updated","container","SyntaxError","containerElement","margin","defaultXCenter","defaultYCenter","xLabel","yLabel","zLabel","passValueFn","xValueLabel","yValueLabel","zValueLabel","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","getMouseX","clientX","targetTouches","getMouseY","clientY","Emitter","_setScale","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","dataMatrix","xIndex","yIndex","trans","screen","bottom","pointRight","pointTop","pointCross","hasChildNodes","firstChild","position","noCanvas","fontWeight","padding","innerHTML","onmousedown","_onMouseDown","ontouchstart","_onTouchStart","onmousewheel","_onWheel","ontooltip","_onTooltip","onkeydown","setSize","_resizeCanvas","clientHeight","animationStart","slider","play","animationStop","stop","_resizeCenter","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","textAlign","textBaseline","fillText","visible","setValues","setPlayInterval","onchange","getIndex","selectValue","setOnChangeCallback","lineStyle","getLabel","getSelectedValue","prettyStep","text","xText","yText","zText","xMin2d","xMax2d","gridLenX","gridLenY","textMargin","armAngle","V","R","G","B","C","Hi","cross","topSideVisible","zAvg","transBottom","dist","sortDepth","aDiff","bDiff","crossproduct","crossProduct","radius","arc","PI","surface","corners","xWidth","yWidth","surfaces","center","avg","transCenter","leftButtonDown","_onMouseUp","which","button","touchDown","startMouseX","startMouseY","startStart","startEnd","startArmRotation","cursor","onmousemove","_onMouseMove","onmouseup","diffX","diffY","horizontalNew","verticalNew","snapAngle","snapValue","parameters","emit","boundingRect","mouseX","mouseY","tooltipTimeout","_hideTooltip","dataPoint","_dataPointFromXY","_showTooltip","ontouchmove","_onTouchMove","ontouchend","_onTouchEnd","delta","wheelDelta","detail","oldLength","newLength","_insideTriangle","triangle","bs","cs","distMax","closestDataPoint","closestDist","triangle1","triangle2","distX","distY","sqrt","line","dot","dom","borderRadius","boxShadow","borderLeft","contentWidth","offsetWidth","contentHeight","offsetHeight","lineHeight","dotWidth","dotHeight","mixin","_callbacks","once","self","removeListener","removeAllListeners","callbacks","cb","listeners","hasListeners","sub","sum","armLocation","armRotation","armLength","cameraLocation","cameraRotation","calculateCameraOrientation","rot","graph","onLoadCallback","loadInBackground","isLoaded","getLoadedProgress","getColumn","getValues","dataView","progress","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","log","LN10","step1","pow","step2","step5","toPrecision","getStep","groups","forthArgument","defaultOptions","autoResize","orientation","maxHeight","minHeight","_create","body","domProps","emitter","bind","hiddenDates","getScale","timeAxis","toScreen","_toScreen","toGlobalScreen","_toGlobalScreen","toTime","_toTime","toGlobalTime","_toGlobalTime","range","currentTime","customTime","itemSet","itemsData","groupsData","setGroups","setItems","_redraw","Core","markDirty","refreshItems","newDataSet","initialLoad","dataRange","_getDataRange","setWindow","animate","fit","setSelection","focus","getSelection","itemData","getItemRange","dataset","minItem","maxStartItem","maxEndItem","setup","Hammer","READY","Event","determineEventTypes","Utils","each","gestures","gesture","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","src","merge","handler","iterator","inStr","find","inArray","hasParent","node","parent","getCenter","touches","pageX","pageY","touch","getVelocity","deltaTime","deltaX","deltaY","getAngle","touch1","touch2","atan2","getDirection","getDistance","getRotation","isVertical","setPrefixedCss","toggle","prefixes","toCamelCase","toggleBehavior","falseFn","onselectstart","ondragstart","str","preventMouseEvents","started","shouldDetect","hook","eventType","onTouchHandler","ev","triggerType","srcType","isPointer","isMouse","buttons","PointerEvent","matchType","updatePointer","doDetect","reset","touchList","getTouchList","touchListLength","triggerChange","trigger","changedLength","changedTouches","evData","collectEventData","identifiers","identifier","pointerType","timeStamp","srcEvent","preventManipulation","stopPropagation","stopDetect","pointers","touchlist","pointer","pointerEvent","pointerId","pt","MSPOINTER_TYPE_MOUSE","MSPOINTER_TYPE_TOUCH","MSPOINTER_TYPE_PEN","detection","current","previous","stopped","startDetect","inst","eventData","startEvent","lastEvent","lastCalcEvent","futureCalcEvent","lastCalcData","extendEventData","instOptions","getCalculatedData","cur","recalc","calcEv","calcData","velocity","angle","velocityX","velocityY","interimAngle","interimDirection","startEv","lastEv","rotation","eventStartHandler","eventHandlers","createEvent","initEvent","dispatchEvent","enable","state","dispose","eh","dragGesture","dragMaxTouches","triggered","dragMinDistance","startCenter","dragDistanceCorrection","factor","dragLockToAxis","dragLockMinDistance","lastDirection","dragBlockVertical","dragBlockHorizontal","Drag","Gesture","holdGesture","timer","holdTimeout","holdThreshold","Hold","Release","Swipe","swipeMinTouches","swipeMaxTouches","swipeVelocityX","swipeVelocityY","tapGesture","sincePrev","didDoubleTap","hasMoved","tapMaxDistance","tapMaxTime","doubleTapInterval","doubleTapDistance","tapAlways","Tap","Touch","preventMouse","transformGesture","scaleThreshold","rotationThreshold","transformMinScale","transformMinRotation","Transform","deltaDifference","scaleOffset","startToFront","endToFront","moveable","zoomable","zoomMin","zoomMax","animateTimer","_onDragStart","_onDrag","_onDragEnd","_onHold","_onMouseWheel","_onTouch","_onPinch","validateDirection","getPointer","hammerUtil","byUser","_cancelAnimation","initStart","initEnd","initTime","anyChanged","dragging","done","changed","_applyRange","updateHiddenDates","newStart","newEnd","getRange","conversion","totalHidden","previousDelta","allowDragging","getHiddenDurationBetween","diffRange","safeStart","snapAwayFromHidden","safeEnd","fakeGesture","pointerDate","_pointerToDate","zoom","centerDate","hiddenDuration","hiddenDurationBefore","getHiddenDurationBefore","hiddenDurationAfter","move","_isResized","resized","_previousWidth","_previousHeight","convertHiddenOptions","repeat","dateItem","centerContainer","totalRange","pixelTime","startDate","endDate","runUntil","dayOffset","removeDuplicates","startHidden","isHidden","endHidden","rangeStart","rangeEnd","hidden","safeDates","printDates","stepOverHiddenDates","timeStep","previousTime","stepInHidden","currentValue","newValue","switchedYear","switchedMonth","switchedDay","correctTimeForHidden","totalDuration","partialDuration","accumulatedHiddenDuration","getAccumulatedHiddenDuration","newTime","timeOffset","requiredDuration","previousPoint","correctionEnabled","Activator","backgroundVertical","backgroundHorizontal","leftContainer","rightContainer","shadowTop","shadowBottom","shadowTopLeft","shadowBottomLeft","shadowTopRight","shadowBottomRight","properties","_redrawTimer","events","isActive","scrollTop","scrollTopMin","redrawCount","clickToUse","activator","_initAutoResize","component","active","_stopAutoResize","setCustomTime","getCustomTime","getVisibleItems","what","getWindow","borderRootHeight","borderRootWidth","autoHeight","containerHeight","centerWidth","_updateScrollTop","visibilityTop","visibilityBottom","visibility","MAX_REDRAWS","repaint","setCurrentTime","getCurrentTime","_startAutoResize","_onResize","lastWidth","lastHeight","watchTimer","setInterval","initialScrollTop","oldScrollTop","_getScrollTop","newScrollTop","_setScrollTop","align","groupOrder","selectable","editable","updateTime","updateGroup","snap","onAdd","onUpdate","onMove","onRemove","onMoving","axis","itemOptions","itemListeners","_onAdd","_onUpdate","_onRemove","groupListeners","_onAddGroups","_onUpdateGroups","_onRemoveGroups","groupIds","selection","stackDirty","touchParams","UNGROUPED","BACKGROUND","box","foreground","labelSet","_updateUngrouped","backgroundGroup","show","_onSelectItem","_onMultiSelectItem","_onAddItem","addCallback","dirty","displayed","hide","ii","unselect","select","groupId","rawVisibleItems","visibleItems","_deselect","_orderGroups","visibleInterval","zoomed","lastVisibleInterval","restack","firstGroup","_firstGroup","firstMargin","nonFirstMargin","groupMargin","groupResized","firstGroupIndex","firstGroupId","ungrouped","_getGroupId","getLabelSet","oldItemsData","getItems","_order","getGroups","removeItem","_getType","_removeItem","groupData","groupOptions","oldGroupId","oldGroup","_constructByEndArray","endArray","itemFromTarget","selected","dragLeftItem","dragRightItem","initialX","itemProps","offsetLeft","newProps","initial","groupFromTarget","_updateItemProps","_moveToGroup","changes","ctrlKey","shiftKey","oldSelection","newSelection","xAbs","newItem","_getItemRange","_item","itemSetFromTarget","minimumStep","autoScale","FORMAT","minorLabels","majorLabels","setFormat","setMinimumStep","first","roundToMinor","setMonth","setDate","setHours","setMinutes","setSeconds","setMilliseconds","getMilliseconds","getSeconds","getMinutes","getHours","hasNext","setScale","setAutoScale","stepYear","stepMonth","stepDay","stepHour","stepMinute","stepSecond","stepMillisecond","isMajor","getLabelMinor","getLabelMajor","getClassName","even","today","currentWeek","currentMonth","currentYear","subgroups","subgroupIndex","subgroupOrderer","subgroupOrder","byStart","byEnd","checkRangedItems","inner","marker","Element","title","getLabelWidth","_updateVisibleItems","markerHeight","lastMarkerHeight","nostack","_calculateHeight","offsetTop","repositionY","resetSubgroups","subgroup","setParent","orderSubgroups","_checkIfVisible","sortArray","sortField","removeFromDataSet","startArray","orderByStart","orderByEnd","oldVisibleItems","visibleItemsLookup","lowerBound","upperBound","_checkIfVisibleWithReference","initialPosByStart","_traceVisible","initialPosByEnd","repositionX","initialPos","breakCondition","isVisible","EPSILON","aTime","bTime","force","iMax","collidingItem","jj","collision","newTop","baseClassName","_updateContents","_updateTitle","_updateDataAttributes","_updateStyle","getComputedStyle","maxWidth","_repaintDeleteButton","_repaintDragLeft","_repaintDragRight","contentLeft","parentWidth","boxWidth","dragLeft","dragRight","deleteButton","template","removeAttribute","dataAttributes","attributes","setAttribute","itemSetHeight","marginLeft","emptyContent","onTop","itemSubgroup","overlay","prevent_default","_onTapOverlay","windowHammer","_hasParent","deactivate","keycharm","escListener","activate","display","unbind","__WEBPACK_AMD_DEFINE_FACTORY__","__WEBPACK_AMD_DEFINE_ARRAY__","_exportFunctions","_bound","keydown","keyup","_keys","fromCharCode","down","handleEvent","up","keyCode","bound","bindAll","getKey","newBindings","lines","majorTexts","minorTexts","lineTop","showMinorLabels","showMajorLabels","parentChanged","_calculateCharSize","minorLabelHeight","minorCharHeight","majorLabelHeight","majorCharHeight","minorLineHeight","minorLineWidth","majorLineHeight","majorLineWidth","foregroundNextSibling","nextSibling","backgroundNextSibling","_repaintLabels","timeLabelsize","minorCharWidth","prevLine","xPrev","xFirstMajorLabel","_repaintMinorText","_repaintMajorText","_repaintMajorLine","_repaintMinorLine","leftTime","leftText","widthText","majorCharWidth","createTextNode","childNodes","nodeValue","measureCharMinor","measureCharMajor","showCurrentTime","substring","currentTimeTimer","custom","showCustomTime","eventParams","drag","linegraph","getLegend","isGroupVisible","yAxisOrientation","defaultGroup","sampling","graphHeight","shaded","barChart","handleOverlap","catmullRom","parametrization","alpha","dataAxis","icons","alignZeros","customRange","legend","abortedGraphUpdate","updateSVGheight","updateSVGheightOnResize","lastStart","svgElements","groupsUsingDefaultStyles","COUNTER","svg","framework","BarGraphFunctions","yAxisLeft","yAxisRight","legendLeft","legendRight","_updateAllGroupData","_updateGroup","removeGroup","addGroup","groupsContent","ungroupedCounter","forceGraphUpdate","_updateGraph","rangePerPixelInv","preprocessedGroupData","processedGroupData","groupRanges","changeCalled","minDate","maxDate","_getRelevantData","_applySampling","_convertXcoordinates","_getYRanges","_updateYAxis","MAX_CYCLES","_convertYcoordinates","draw","dataContainer","guess","increment","amountOfPoints","xDistance","pointsPerPixel","sampledData","barCombinedDataLeft","barCombinedDataRight","getYRange","getStackedBarYRange","minVal","maxVal","yAxisLeftUsed","yAxisRightUsed","minLeft","minRight","maxLeft","maxRight","ignore","_toggleAxisVisiblity","drawIcons","master","lineOffset","stepPixelsForced","stepPixels","zeroCrossing","axisUsed","datapoints","xValue","yValue","extractedData","svgHeight","labelValue","convertValue","setZeroPosition","linegraphOptions","majorLinesOffset","minorLinesOffset","labelOffsetX","labelOffsetY","iconWidth","decimals","linegraphSVG","DOMelements","labels","conversionFactor","minWidth","iconsRemoved","amountOfGroups","lineContainer","graphOptions","_redrawGroupIcons","iconHeight","iconOffset","drawIcon","_cleanupIcons","activeGroups","_redrawLabels","_redrawTitle","deadSpace","marginRange","amountOfSteps","stepDifference","zeroStepDifference","marginEnd","valueAtZero","marginStartPos","maxLabelSize","_redrawLabel","_redrawLine","titleWidth","titleCharHeight","invertedValue","convertedValue","characterHeight","largestWidth","textMinor","textMajor","textTitle","measureCharTitle","titleCharWidth","stepIndex","marginStart","majorSteps","minorSteps","setFirst","safeSize","minimumStepValue","orderOfMagnitude","minorStepIdx","magnitudefactor","solutionFound","stepSize","niceStart","niceEnd","rounded","exp","cnt","usingDefaultStyle","zeroPosition","Line","Bar","Points","SVGcontainer","path","fillPath","fillHeight","outline","barWidth","bar1Height","bar2Height","icon","_catmullRom","_linear","dFill","_catmullRomUniform","p0","bp1","bp2","normalization","d1","d2","d3","N","d3powA","d2powA","d3pow2A","d2pow2A","d1pow2A","d1powA","Bargraph","barCombinedData","coreDistance","drawData","combinedData","intersections","barPoints","_getDataIntersections","heightOffset","_getSafeDrawData","nextKey","amount","resolved","prevKey","accumulated","groupLabel","_getStackedBarYRange","xpos","side","iconSize","iconSpacing","textArea","scrollableHeight","drawLegendIcons","paddingTop","_determineBrowserMethod","_initializeMixinLoaders","renderRefreshRate","renderTimestep","renderTime","physicsTime","runDoubleSpeed","physicsDiscreteStepsize","initializing","triggerFunctions","edit","editEdge","connect","del","customScalingFunction","nodes","mass","radiusMin","radiusMax","shape","image","fontColor","fontSize","fontFace","fontFill","fontStrokeWidth","fontStrokeColor","fontDrawThreshold","scaleFontWithValue","fontSizeMin","fontSizeMax","fontSizeMaxVisible","level","borderWidthSelected","edges","widthSelectionMultiplier","hoverWidth","labelAlignment","arrowScaleFactor","dash","gap","altLength","inheritColor","useGradients","configurePhysics","physics","barnesHut","thetaInverted","gravitationalConstant","centralGravity","springLength","springConstant","damping","repulsion","nodeDistance","hierarchicalRepulsion","clustering","navigation","keyboard","speed","bindToWindow","dataManipulation","initiallyVisible","hierarchicalLayout","levelSeparation","nodeSpacing","layout","freezeForStabilization","smoothCurves","dynamic","roundness","maxVelocity","minVelocity","stabilize","stabilizationIterations","zoomExtentOnStabilize","dragNetwork","dragNodes","hideEdgesOnDrag","hideNodesOnDrag","useDefaultGroups","constants","pixelRatio","hoverObj","controlNodesActive","navigationHammers","existing","_new","animationSpeed","animationEasingFunction","animating","easingTime","sourceScale","targetScale","sourceTranslation","targetTranslation","lockedOnNodeId","lockedOnNodeOffset","touchTime","redrawRequested","images","setOnloadCallback","_requestRedraw","xIncrement","yIncrement","zoomIncrement","_loadPhysicsSystem","_loadSectorSystem","_loadClusterSystem","_loadSelectionSystem","_loadHierarchySystem","_setTranslation","freezeSimulationEnabled","cachedFunctions","startedStabilization","stabilized","draggingNodes","calculationNodes","calculationNodeIndices","nodeIndices","canvasTopLeft","canvasBottomRight","pointerPosition","areaCenter","previousScale","nodesData","edgesData","nodesListeners","_addNodes","_updateNodes","_removeNodes","edgesListeners","_addEdges","_updateEdges","_removeEdges","moving","_setupHierarchicalLayout","zoomExtent","startWithClustering","MixinLoader","browserType","requiresTimeout","_getScriptPath","scripts","getElementsByTagName","_getRange","specificNodes","minY","maxY","minX","maxX","boundingBox","nodeId","_findCenter","initialZoom","disableStart","zoomLevel","positionDefined","predefinedPosition","numberOfNodes","initialMaxNodes","yDistance","xZoomLevel","yZoomLevel","animation","_updateNodeIndexList","_clearNodeIndexList","idx","_unselectAll","_createManipulatorBar","dotData","DOTToGraph","gephi","gephiData","parseGephi","_setNodes","_setEdges","_putDataInSector","_resetLevels","_stabilize","onEdit","onEditEdge","onConnect","onDelete","editMode","newColorObj","groupname","_createKeyBinds","_loadNavigationControls","_loadManipulationSystem","_configureSmoothCurves","_bindHammer","_markAllEdgesAsDirty","tabIndex","devicePixelRatio","webkitBackingStorePixelRatio","mozBackingStorePixelRatio","msBackingStorePixelRatio","oBackingStorePixelRatio","backingStorePixelRatio","setTransform","pinch","_onTap","_onDoubleTap","_onMouseMoveTitle","hammerFrame","_onRelease","_moveUp","_yStopMoving","_moveDown","_moveLeft","_xStopMoving","_moveRight","_zoomIn","_stopZoom","_zoomOut","_deleteSelected","_cleanupPhysicsConfiguration","_recursiveDOMDelete","DOMobject","_getPointer","pinched","_getScale","_handleTouch","_handleDragStart","_getNodeAt","_getTranslation","isSelected","_selectObject","nodeIds","objectId","selectionObj","xFixed","yFixed","_handleOnDrag","releaseNode","_XconvertDOMtoCanvas","_XconvertCanvasToDOM","_YconvertDOMtoCanvas","_YconvertCanvasToDOM","_handleDragEnd","_handleTap","_handleDoubleTap","_handleOnHold","_handleOnRelease","_zoom","scaleOld","preScaleDragPointer","DOMtoCanvas","scaleFrac","tx","ty","updateClustersDefault","postScaleDragPointer","canvasToDOM","popupVisible","popup","_checkHidePopup","setPosition","checkShow","_checkShowPopup","popupTimer","edgeId","_getEdgeAt","_hoverObject","_blurObject","previousPopupObjId","popupObj","nodeUnderCursor","popupType","overlappingNodes","isOverlappingWith","getTitle","overlappingEdges","edge","connected","popupTargetType","popupTargetId","setText","pointerObj","stillOnObj","overNode","emitEvent","oldWidth","oldHeight","oldNodesData","_updateSelection","_updateCalculationNodes","_reconnectEdges","_updateValueRange","updateLabels","changedData","setProperties","colorDirty","_removeFromSelection","oldEdgesData","oldEdge","disconnect","showInternalIds","_createBezierNodes","via","sectors","dynamicEdges","valueTotal","setValueRange","requestAnimationFrame","save","translate","_doInAllSectors","restore","offsetX","offsetY","_drawNodes","alwaysShow","setScaleAndPos","inArea","sMax","_drawEdges","_drawControlNodes","_freezeDefinedNodes","_physicsTick","_restoreFrozenNodes","fixedData","_isMoving","vmin","isMoving","_discreteStepNodes","nodesPresent","discreteStepLimited","discreteStep","vminCorrected","_revertPhysicsState","revertPosition","_revertPhysicsTick","_doInAllActiveSectors","_doInSupportSector","mainMovingStatus","supportMovingStatus","mainMoving","_animationStep","_handleNavigation","startTime","renderStartTime","mozRequestAnimationFrame","webkitRequestAnimationFrame","msRequestAnimationFrame","iterations","freezeSimulation","freeze","parentEdgeId","internalMultiplier","positionBezierNode","storePosition","storePositions","dataArray","allowedToMoveX","allowedToMoveY","getPositions","focusOnNode","nodePosition","lockedOnNode","easingFunction","animateView","locked","_transitionRedraw","viewCenter","distanceFromCenter","_classicRedraw","_lockedRedraw","getCenterCoordinates","getBoundingBox","getConnectedNodes","nodeList","nodeObj","toId","fromId","getEdgesFromNode","edgesList","generateColorObject","networkConstants","widthSelected","labelDimensions","yLine","dirtyLabel","fromBackup","toBackup","originalFromId","originalToId","widthFixed","lengthFixed","controlNodesEnabled","controlNodes","positions","connectedNode","_drawLine","_drawArrow","_drawArrowCenter","_drawDashLine","attachEdge","detachEdge","widthDiff","xFrom","yFrom","xTo","yTo","xObj","yObj","_getDistanceToEdge","_getColor","colorObj","fromColor","toColor","grd","createLinearGradient","addColorStop","_getLineWidth","_line","midpointX","midpointY","_pointOnLine","_label","resize","_circle","_pointOnCircle","networkScaleInv","_getViaCoordinates","xVia","yVia","pi","originalAngle","myAngle","quadraticCurveTo","lineCount","measureText","_rotateForLabelAlignment","_drawLabelRect","_drawLabelText","angleInDegrees","rotate","lineMargin","fillRect","lineJoin","strokeText","setLineDash","pattern","lineDashOffset","lineCap","dashedLine","percentage","arrow","_pointOnBezier","_findBorderPosition","distanceToBorder","distanceToNodes","difference","arrowPos","guidePos","edgeSegmentLength","toBorderDist","toBorderPoint","x1","y1","x2","y2","x3","y3","lastX","lastY","minDistance","_getDistanceToLine","px","py","something","u","nodeIdFrom","nodeIdTo","maxNodeSizeIncrements","nodeScaling","getControlNodeFromPosition","getControlNodeToPosition","_enableControlNodes","_disableControlNodes","_getSelectedControlNode","fromDistance","toDistance","_restoreControlNodes","controlnodeFromPos","fromBorderDist","fromBorderPoint","controlnodeToPos","imagelist","grouplist","reroutedEdges","horizontalAlignLeft","verticalAlignTop","baseRadiusValue","radiusFixed","preassignedLevel","hierarchyEnumerated","fx","fy","vx","vy","previousState","resetCluster","clusterSession","clusterSizeWidthFactor","clusterSizeHeightFactor","clusterSizeRadiusFactor","growthIndicator","networkScale","formationScale","clusterSize","containedNodes","containedEdges","clusterSessions","originalLabel","triggerFunction","groupObj","imageObj","load","brokenImage","_drawDatabase","_resizeDatabase","_drawBox","_resizeBox","_drawCircle","_resizeCircle","_drawEllipse","_resizeEllipse","_drawImage","_resizeImage","_drawCircularImage","_resizeCircularImage","_drawText","_resizeText","_drawDot","_resizeShape","_drawSquare","_drawTriangle","_drawTriangleDown","_drawStar","_drawIcon","_resizeIcon","_reset","clearSizeCache","_setForce","_addForce","storeState","isFixed","radiusDiff","fontDiff","_drawImageAtPosition","globalAlpha","drawImage","_drawImageLabel","getTextSize","_swapToImageResizeWhenImageLoaded","diameter","centerX","centerY","_drawRawCircle","circle","clip","textSize","clusterLineWidth","selectionLineWidth","roundRect","database","defaultSize","ellipse","_drawShape","radiusMultiplier","_icon","iconTextSpacing","relativeIconSize","iconFontFace","iconColor","baseline","labelUnderNode","relativeFontSize","strokecolor","inView","clearVelocity","updateVelocity","massBeforeClustering","energyBefore","defaultIndex","groupsArray","groupIndex","DEFAULT","groupName","imageBroken","url","brokenUrl","img","Image","onload","onerror","error","fontFamily","parseDOT","parseGraph","nextPreview","isAlphaNumeric","regexAlphaNumeric","o","addNode","graphs","attr","addEdge","createEdge","getToken","tokenType","TOKENTYPE","NULL","isComment","DELIMITER","c2","DELIMITERS","IDENTIFIER","newSyntaxError","UNKNOWN","chop","parseStatements","parseStatement","subgraph","parseSubgraph","parseEdge","parseAttributeStatement","parseNodeStatement","subgraphs","parseAttributeList","message","maxLength","forEach2","elem1","elem2","graphData","dotNode","graphNode","convertEdge","dotEdge","graphEdge","subEdge","{","}","[","]",";","=",",","->","--","gephiJSON","allowedToMove","gEdges","gNodes","gEdge","gNode","PhysicsMixin","ClusterMixin","SectorsMixin","SelectionMixin","ManipulationMixin","NavigationMixin","HierarchicalLayoutMixin","_loadMixin","sourceVariable","mixinFunction","_clearMixin","_loadSelectedForceSolver","_loadPhysicsConfiguration","hubThreshold","activeSector","drawingNode","blockConnectingEdgeSelection","forceAppendSelection","manipulationDiv","editModeDiv","closeDiv","_cleanNavigation","_loadNavigationElements","graphToggleSmoothCurves","graph_toggleSmooth","getElementById","graphRepositionNodes","showValueOfRange","repositionNodes","graphGenerateOptions","optionsSpecific","radioButton1","radioButton2","checked","backupConstants","optionsDiv","switchConfigurations","radioButton","querySelector","tableId","table","_restoreNodes","constantsVariableName","valueId","rangeValue","_overWriteGraphConstants","RepulsionMixin","HierarchialRepulsionMixin","BarnesHutMixin","_toggleBarnesHut","barnesHutTree","_initializeForceCalculation","clusterThreshold","clusterToFit","reduceToNodes","_calculateForces","_calculateGravitationalForces","_calculateNodeForces","_calculateSpringForcesWithSupport","_calculateHierarchicalSpringForces","_calculateSpringForces","supportNodes","supportNodeId","gravity","gravityForce","_sector","edgeLength","springForce","edgeGrowth","combinedClusterSize","node1","node2","node3","_calculateSpringForce","physicsConfiguration","maxGravitational","maxSpring","hierarchicalLayoutDirections","parentElement","rangeElement","radioButton3","graph_repositionNodes","graph_generateOptions","dynamicSmoothCurves","nameArray","repulsingForce","a_base","minimumDistance","distanceAmplification","forceAmplification","steepness","springFx","springFy","totalFx","totalFy","correctionFx","correctionFy","nodeCount","_formBarnesHutTree","_getForceContribution","NW","NE","SW","SE","parentBranch","childrenCount","centerOfMass","calcSize","MAX_VALUE","sizeDiff","minimumTreeSize","rootSize","halfRootSize","_splitBranch","_placeInTree","_updateBranchMass","totalMass","totalMassInv","biggestSize","skipMassUpdate","_placeInRegion","region","containedNode","_insertRegion","childSize","_drawTree","_drawBranch","branch","_switchToSector","sectorId","sectorType","_switchToActiveSector","_switchToFrozenSector","_switchToSupportSector","_loadLatestSector","_previousSector","_setActiveSector","newId","_forgetLastSector","_createNewSector","_deleteActiveSector","_deleteFrozenSector","_freezeSector","_activateSector","_mergeThisWithFrozen","_collapseThisToSingleCluster","_addSector","sector","unqiueIdentifier","_collapseSector","screenSizeThreshold","previousSector","runFunction","argument","returnValues","_doInAllFrozenSectors","_drawSectorNodes","_drawAllSectorNodes","_getNodesOverlappingWith","_getAllNodesOverlappingWith","_pointerToPositionObject","positionObject","_getEdgesOverlappingWith","_getAllEdgesOverlappingWith","_addToSelection","_addToHover","doNotTrigger","_unselectClusters","_getSelectedNodeCount","_getSelectedNode","_getSelectedEdge","_getSelectedEdgeCount","_getSelectedObjectCount","_selectionIsEmpty","_clusterInSelection","_selectConnectedEdges","_hoverConnectedEdges","_unselectConnectedEdges","append","highlightEdges","overrideSelectable","DOM","openCluster","_manipulationReleaseOverload","_navigationReleaseOverload","getSelectedNodes","edgeIds","getSelectedEdges","idArray","selectNodes","RangeError","selectEdges","_clearManipulatorBar","manipulationDOM","_restoreOverloadedFunctions","functionName","_toggleEditMode","toolbar","boundFunction","edgeBeingEdited","selectedControlNode","_createAddNodeToolbar","_createAddEdgeToolbar","_editNode","_createEditEdgeToolbar","_addNode","_handleConnect","_finishConnect","_selectControlNode","_controlNodeDrag","_releaseControlNode","newNode","_editEdge","alert","targetNode","connectionEdge","connectFromId","_createEdge","defaultData","finalizedData","sourceNodeId","targetNodeId","selectedNodes","selectedEdges","navigationDivs","navigationDivActions","_stopMovement","_zoomExtent","hubsize","definedLevel","undefinedLevel","_changeConstants","_determineLevels","_determineLevelsDirected","distribution","_getDistribution","_placeNodesByHierarchy","minPos","_placeBranchNodes","maxCount","_setLevel","firstNode","minLevel","_setLevelDirected","parentId","parentLevel","childNode","nodeMoved","back","editNode","addDescription","edgeDescription","editEdgeDescription","createEdgeError","deleteClusterError","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"],"mappings":"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WAAYG,OAAQF,OAAQ,UAAWD,WAAY,aACxIC,OAAQ,UAAWD,WAAY,UAAWE,WAAYD,OAAQ,UAAWD,WAAY,WAAYG,OAAQF,OAAQ,UAAWD,WAAY,aACxIC,OAAQ,UAAWD,WAAY,UAAWE,WAAYD,OAAQ,UAAWD,WAAY,WAAYG,OAAQF,OAAQ,UAAWD,WAAY,aACxIC,OAAQ,UAAWD,WAAY,UAAWE,WAAYD,OAAQ,UAAWD,WAAY,WAAYG,OAAQF,OAAQ,UAAWD,WAAY,aACxIC,OAAQ,UAAWD,WAAY,UAAWE,WAAYD,OAAQ,UAAWD,WAAY,WAAYG,OAAQF,OAAQ,UAAWD,WAAY,aACxIC,OAAQ,UAAWD,WAAY,UAAWE,WAAYD,OAAQ,UAAWD,WAAY,WAAYG,OAAQF,OAAQ,UAAWD,WAAY,aACxIC,OAAQ,UAAWD,WAAY,UAAWE,WAAYD,OAAQ,UAAWD,WAAY,WAAYG,OAAQF,OAAQ,UAAWD,WAAY,aACxIC,OAAQ,UAAWD,WAAY,UAAWE,WAAYD,OAAQ,UAAWD,WAAY,WAAYG,OAAQF,OAAQ,UAAWD,WAAY,aAExIC,OAAQ,UAAWD,WAAY,UAAWE,WAAYD,OAAQ,UAAWD,WAAY,WAAYG,OAAQF,OAAQ,UAAWD,WAAY,aAExIC,OAAQ,UAAWD,WAAY,UAAWE,WAAYD,OAAQ,UAAWD,WAAY,WAAYG,OAAQF,OAAQ,UAAWD,WAAY,aACxIC,OAAQ,UAAWD,WAAY,UAAWE,WAAYD,OAAQ,UAAWD,WAAY,WAAYG,OAAQF,OAAQ,UAAWD,WAAY,aACxIC,OAAQ,UAAWD,WAAY,UAAWE,WAAYD,OAAQ,UAAWD,WAAY,WAAYG,OAAQF,OAAQ,UAAWD,WAAY,aACxIC,OAAQ,UAAWD,WAAY,UAAWE,WAAYD,OAAQ,UAAWD,WAAY,WAAYG,OAAQF,OAAQ,UAAWD,WAAY,aACxIC,OAAQ,UAAWD,WAAY,UAAWE,WAAYD,OAAQ,UAAWD,WAAY,WAAYG,OAAQF,OAAQ,UAAWD,WAAY,aACxIC,OAAQ,UAAWD,WAAY,UAAWE,WAAYD,OAAQ,UAAWD,WAAY,WAAYG,OAAQF,OAAQ,UAAWD,WAAY,aACxIC,OAAQ,UAAWD,WAAY,UAAWE,WAAYD,OAAQ,UAAWD,WAAY,WAAYG,OAAQF,OAA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"} \ No newline at end of file diff --git a/dist/vis.min.js b/dist/vis.min.js index 5946fc26..df0babc9 100644 --- a/dist/vis.min.js +++ b/dist/vis.min.js @@ -22,18 +22,18 @@ * * Vis.js may be distributed under either license. */ -"use strict";!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.Queue=i(5),e.Graph3d=i(6),e.graph3d={Camera:i(7),Filter:i(8),Point2d:i(9),Point3d:i(10),Slider:i(11),StepNumber:i(12)},e.Timeline=i(13),e.Graph2d=i(14),e.timeline={DateUtil:i(15),DataStep:i(16),Range:i(17),stack:i(18),TimeStep:i(19),components:{items:{Item:i(31),BackgroundItem:i(32),BoxItem:i(33),PointItem:i(34),RangeItem:i(35)},Component:i(20),CurrentTime:i(21),CustomTime:i(22),DataAxis:i(23),GraphGroup:i(24),Group:i(25),BackgroundGroup:i(26),ItemSet:i(27),Legend:i(28),LineGraph:i(29),TimeAxis:i(30)}},e.Network=i(36),e.network={Edge:i(37),Groups:i(38),Images:i(39),Node:i(40),Popup:i(41),dotparser:i(42),gephiParser:i(43)},e.Graph=function(){throw new Error("Graph is renamed to Network. Please create a graph as new vis.Network(...)")},e.moment=i(44),e.hammer=i(45)},function(t,e,i){var s=i(44);e.isNumber=function(t){return t instanceof Number||"number"==typeof t},e.giveRange=function(t,e,i,s){if(e==t)return.5;var o=1/(e-t);return Math.max(0,(s-t)*o)},e.isString=function(t){return t instanceof String||"string"==typeof t},e.isDate=function(t){if(t instanceof Date)return!0;if(e.isString(t)){var i=o.exec(t);if(i)return!0;if(!isNaN(Date.parse(t)))return!0}return!1},e.isDataTable=function(t){return"undefined"!=typeof google&&google.visualization&&google.visualization.DataTable&&t instanceof google.visualization.DataTable},e.randomUUID=function(){var t=function(){return Math.floor(65536*Math.random()).toString(16)};return t()+t()+"-"+t()+"-"+t()+"-"+t()+"-"+t()+t()+t()},e.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},e.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},e.convert=function(t,i){var n;if(void 0===t)return void 0;if(null===t)return null;if(!i)return t;if("string"!=typeof i&&!(i instanceof String))throw new Error("Type must be a string");switch(i){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(e.isNumber(t))return new Date(t);if(t instanceof Date)return new Date(t.valueOf());if(s.isMoment(t))return new Date(t.valueOf());if(e.isString(t))return n=o.exec(t),n?new Date(Number(n[1])):s(t).toDate();throw new Error("Cannot convert object of type "+e.getType(t)+" to type Date");case"Moment":if(e.isNumber(t))return s(t);if(t instanceof Date)return s(t.valueOf());if(s.isMoment(t))return s(t);if(e.isString(t))return n=o.exec(t),s(n?Number(n[1]):t);throw new Error("Cannot convert object of type "+e.getType(t)+" to type Date");case"ISODate":if(e.isNumber(t))return new Date(t);if(t instanceof Date)return t.toISOString();if(s.isMoment(t))return t.toDate().toISOString();if(e.isString(t))return n=o.exec(t),n?new Date(Number(n[1])).toISOString():new Date(t).toISOString();throw new Error("Cannot convert object of type "+e.getType(t)+" to type ISODate");case"ASPDate":if(e.isNumber(t))return"/Date("+t+")/";if(t instanceof Date)return"/Date("+t.valueOf()+")/";if(e.isString(t)){n=o.exec(t);var r;return r=n?new Date(Number(n[1])).valueOf():new Date(t).valueOf(),"/Date("+r+")/"}throw new Error("Cannot convert object of type "+e.getType(t)+" to type ASPDate");default:throw new Error('Unknown type "'+i+'"')}};var o=/^\/?Date\((\-?\d+)/i;e.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":Array.isArray(t)?"Array":t instanceof Date?"Date":"Object":"number"==e?"Number":"boolean"==e?"Boolean":"string"==e?"String":e},e.getAbsoluteLeft=function(t){return t.getBoundingClientRect().left+window.pageXOffset},e.getAbsoluteTop=function(t){return t.getBoundingClientRect().top+window.pageYOffset},e.addClassName=function(t,e){var i=t.className.split(" ");-1==i.indexOf(e)&&(i.push(e),t.className=i.join(" "))},e.removeClassName=function(t,e){var i=t.className.split(" "),s=i.indexOf(e);-1!=s&&(i.splice(s,1),t.className=i.join(" "))},e.forEach=function(t,e){var i,s;if(Array.isArray(t))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)},e.toArray=function(t){var e=[];for(var i in t)t.hasOwnProperty(i)&&e.push(t[i]);return e},e.updateProperty=function(t,e,i){return t[e]!==i?(t[e]=i,!0):!1},e.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)},e.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)},e.preventDefault=function(t){t||(t=window.event),t.preventDefault?t.preventDefault():t.returnValue=!1},e.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},e.option={},e.option.asBoolean=function(t,e){return"function"==typeof t&&(t=t()),null!=t?0!=t:e||null},e.option.asNumber=function(t,e){return"function"==typeof t&&(t=t()),null!=t?Number(t)||e||null:e||null},e.option.asString=function(t,e){return"function"==typeof t&&(t=t()),null!=t?String(t):e||null},e.option.asSize=function(t,i){return"function"==typeof t&&(t=t()),e.isString(t)?t:e.isNumber(t)?t+"px":i||null},e.option.asElement=function(t,e){return"function"==typeof t&&(t=t()),t||e||null},e.hexToRGB=function(t){var e=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;t=t.replace(e,function(t,e,i,s){return e+e+i+i+s+s});var i=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);return i?{r:parseInt(i[1],16),g:parseInt(i[2],16),b:parseInt(i[3],16)}:null},e.overrideOpacity=function(t,i){if(-1!=t.indexOf("rgb")){var s=t.substr(t.indexOf("(")+1).replace(")","").split(",");return"rgba("+s[0]+","+s[1]+","+s[2]+","+i+")"}var s=e.hexToRGB(t);return null==s?t:"rgba("+s.r+","+s.g+","+s.b+","+i+")"},e.RGBToHex=function(t,e,i){return"#"+((1<<24)+(t<<16)+(e<<8)+i).toString(16).slice(1)},e.parseColor=function(t){var i;if(e.isString(t)){if(e.isValidRGB(t)){var s=t.substr(4).substr(0,t.length-5).split(",");t=e.RGBToHex(s[0],s[1],s[2])}if(e.isValidHex(t)){var o=e.hexToHSV(t),n={h:o.h,s:.45*o.s,v:Math.min(1,1.05*o.v)},r={h:o.h,s:Math.min(1,1.25*o.v),v:.6*o.v},a=e.HSVToHex(r.h,r.h,r.v),h=e.HSVToHex(n.h,n.s,n.v);i={background:t,border:a,highlight:{background:h,border:a},hover:{background:h,border:a}}}else i={background:t,border:t,highlight:{background:t,border:t},hover:{background:t,border:t}}}else i={},i.background=t.background||"white",i.border=t.border||i.background,e.isString(t.highlight)?i.highlight={border:t.highlight,background:t.highlight}:(i.highlight={},i.highlight.background=t.highlight&&t.highlight.background||i.background,i.highlight.border=t.highlight&&t.highlight.border||i.border),e.isString(t.hover)?i.hover={border:t.hover,background:t.hover}:(i.hover={},i.hover.background=t.hover&&t.hover.background||i.background,i.hover.border=t.hover&&t.hover.border||i.border);return i},e.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}};var n={split:function(t){var e={};return t.split(";").forEach(function(t){if(""!=t.trim()){var i=t.split(":"),s=i[0].trim(),o=i[1].trim();e[s]=o}}),e},join:function(t){return Object.keys(t).map(function(e){return e+": "+t[e]}).join("; ")}};e.addCssText=function(t,i){var s=n.split(t.style.cssText),o=n.split(i),r=e.extend(s,o);t.style.cssText=n.join(r)},e.removeCssText=function(t,e){var i=n.split(t.style.cssText),s=n.split(e);for(var o in s)s.hasOwnProperty(o)&&delete i[o];t.style.cssText=n.join(i)},e.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)}},e.HSVToHex=function(t,i,s){var o=e.HSVToRGB(t,i,s);return e.RGBToHex(o.r,o.g,o.b)},e.hexToHSV=function(t){var i=e.hexToRGB(t);return e.RGBToHSV(i.r,i.g,i.b)},e.isValidHex=function(t){var e=/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(t);return e},e.isValidRGB=function(t){t=t.replace(" ","");var e=/rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)/i.test(t);return e},e.selectiveBridgeObject=function(t,i){if("object"==typeof i){for(var s=Object.create(i),o=0;o=r&&o>n;){var h=Math.floor((r+a)/2),d=t[h],l=void 0===s?d[i]:d[i][s],c=e(l);if(0==c)return h;-1==c?r=h+1:a=h-1,n++}return-1},e.binarySearchValue=function(t,e,i,s){for(var o,n,r,a,h=1e4,d=0,l=0,c=t.length-1;c>=l&&h>d;){if(a=Math.floor(.5*(c+l)),o=t[Math.max(0,a-1)][i],n=t[a][i],r=t[Math.min(t.length-1,a+1)][i],n==e)return a;if(e>o&&n>e)return"before"==s?Math.max(0,a-1):a;if(e>n&&r>e)return"before"==s?a:Math.min(t.length-1,a+1);e>n?l=a+1:c=a-1,d++}return-1},e.easeInOutQuad=function(t,e,i,s){var o=i-e;return t/=s/2,1>t?o/2*t*t+e:(t--,-o/2*(t*(t-2)-1)+e)},e.easingFunctions={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return t*(2-t)},easeInOutQuad:function(t){return.5>t?2*t*t:-1+(4-2*t)*t},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return--t*t*t+1},easeInOutCubic:function(t){return.5>t?4*t*t*t:(t-1)*(2*t-2)*(2*t-2)+1},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return 1- --t*t*t*t},easeInOutQuart:function(t){return.5>t?8*t*t*t*t:1-8*--t*t*t*t},easeInQuint:function(t){return t*t*t*t*t},easeOutQuint:function(t){return 1+--t*t*t*t*t},easeInOutQuint:function(t){return.5>t?16*t*t*t*t*t:1+16*--t*t*t*t*t}}},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,s){var o;return e.hasOwnProperty(t)?e[t].redundant.length>0?(o=e[t].redundant[0],e[t].redundant.shift()):(o=document.createElement(t),void 0!==s?i.insertBefore(o,s):i.appendChild(o)):(o=document.createElement(t),e[t]={used:[],redundant:[]},void 0!==s?i.insertBefore(o,s):i.appendChild(o)),e[t].used.push(o),o},e.drawPoint=function(t,i,s,o,n,r){var a;"circle"==s.options.drawPoints.style?(a=e.getSVGElement("circle",o,n),a.setAttributeNS(null,"cx",t),a.setAttributeNS(null,"cy",i),a.setAttributeNS(null,"r",.5*s.options.drawPoints.size)):(a=e.getSVGElement("rect",o,n),a.setAttributeNS(null,"x",t-.5*s.options.drawPoints.size),a.setAttributeNS(null,"y",i-.5*s.options.drawPoints.size),a.setAttributeNS(null,"width",s.options.drawPoints.size),a.setAttributeNS(null,"height",s.options.drawPoints.size)),void 0!==s.options.drawPoints.styles&&a.setAttributeNS(null,"style",s.group.options.drawPoints.styles),a.setAttributeNS(null,"class",s.className+" point");var h=e.getSVGElement("text",o,n);return r&&(r.xOffset&&(t+=r.xOffset),r.yOffset&&(i+=r.yOffset),r.content&&(h.textContent=r.content),r.className&&h.setAttributeNS(null,"class",r.className+" label")),h.setAttributeNS(null,"x",t),h.setAttributeNS(null,"y",i),a},e.drawBar=function(t,i,s,o,n,r,a){if(0!=o){0>o&&(o*=-1,i-=o);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.length=0,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),this.setOptions(e)}var o=i(1),n=i(5);s.prototype.setOptions=function(t){t&&void 0!==t.queue&&(t.queue===!1?this._queue&&(this._queue.destroy(),delete this._queue):(this._queue||(this._queue=n.extend(this,{replace:["add","update","remove"]})),"object"==typeof t.queue&&this._queue.setOptions(t.queue)))},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=[],r=this,a=r._fieldId,h=function(t){var e=t[a];r._data[e]?(e=r._updateItem(t),s.push(e),n.push(t)):(e=r._addItem(t),i.push(e))};if(Array.isArray(t))for(var d=0,l=t.length;l>d;d++)h(t[d]);else if(o.isDataTable(t))for(var c=this._getColumnNames(t),p=0,u=t.getNumberOfRows();u>p;p++){for(var m={},f=0,g=c.length;g>f;f++){var v=c[f];m[v]=t.getValue(p,f)}h(m)}else{if(!(t instanceof Object))throw new Error("Unknown dataType");h(t)}return i.length&&this._trigger("add",{items:i},e),s.length&&this._trigger("update",{items:s,data:n},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,f=[];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))&&f.push(d);else for(l in this._data)this._data.hasOwnProperty(l)&&(d=n._getItem(l,u),(!m||m(d))&&f.push(d));if(i&&i.order&&void 0==t&&this._sort(f,i.order),i&&i.fields){var g=i.fields;if(void 0!=t)d=this._filterFields(d,g);else for(c=0,p=f.length;p>c;c++)f[c]=this._filterFields(f[c],g)}if("DataTable"==a){var v=this._getColumnNames(s);if(void 0!=t)n._appendRow(s,v,d);else for(c=0;cc;c++)s.push(f[c]);return s}return f},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){if(!t)return t;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],this.length--,t}else if(t instanceof Object){var e=t[this._fieldId];if(e&&this._data[e])return delete this._data[e],this.length--,e}return null},s.prototype.clear=function(t){var e=Object.keys(this._data);return this._data={},this.length=0,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.length=0,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.length=0,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.length=e.length,this._trigger("add",{items:e}),this._data.on&&this._data.on("*",this.listener)}},s.prototype.refresh=function(){for(var t,e=this._data.getIds({filter:this._options&&this._options.filter}),i={},s=[],o=[],n=0;ns;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))}this.length+=d.length-c.length,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){function e(t){this.delay=null,this.max=1/0,this._queue=[],this._timeout=null,this._extended=null,this.setOptions(t)}e.prototype.setOptions=function(t){t&&"undefined"!=typeof t.delay&&(this.delay=t.delay),t&&"undefined"!=typeof t.max&&(this.max=t.max),this._flushIfNeeded()},e.extend=function(t,i){var s=new e(i);if(void 0!==t.flush)throw new Error("Target object already has a property flush");t.flush=function(){s.flush()};var o=[{name:"flush",original:void 0}];if(i&&i.replace)for(var n=0;nthis.max&&this.flush(),clearTimeout(this._timeout),this.queue.length>0&&"number"==typeof this.delay){var t=this;this._timeout=setTimeout(function(){t.flush()},this.delay)}},e.prototype.flush=function(){for(;this._queue.length>0;){var t=this._queue.shift();t.fn.apply(t.context||t.fn,t.args||[])}},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");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";var o=function(t){return t};this.xValueLabel=o,this.yValueLabel=o,this.zValueLabel=o,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 p,this.eye=new l(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)}function o(t){return"clientX"in t?t.clientX:t.targetTouches[0]&&t.targetTouches[0].clientX||0}function n(t){return"clientY"in t?t.clientY:t.targetTouches[0]&&t.targetTouches[0].clientY||0}var r=i(56),a=i(3),h=i(4),d=i(1),l=i(10),c=i(9),p=i(7),u=i(8),m=i(11),f=i(12);r(s.prototype),s.prototype._setScale=function(){this.scale=new l(1/(this.xMax-this.xMin),1/(this.yMax-this.yMin),1/(this.zMax-this.zMin)),this.keepAspectRatio&&(this.scale.x3&&(this.colFilter=3);else{if(this.style!==s.STYLE.DOTCOLOR&&this.style!==s.STYLE.DOTSIZE&&this.style!==s.STYLE.BARCOLOR&&this.style!==s.STYLE.BARSIZE)throw'Unknown style "'+this.style+'"';this.colX=0,this.colY=1,this.colZ=2,this.colValue=3,t.getNumberOfColumns()>4&&(this.colFilter=4)}},s.prototype.getNumberOfRows=function(t){return t.length},s.prototype.getNumberOfColumns=function(t){var e=0;for(var i in t[0])t[0].hasOwnProperty(i)&&e++;return e},s.prototype.getDistinctValues=function(t,e){for(var i=[],s=0;st[s][e]&&(i.min=t[s][e]),i.maxt;t++){var m=(t-p)/(u-p),g=240*m,v=this._hsv2rgb(g,1,1);c.strokeStyle=v,c.beginPath(),c.moveTo(h,r+t),c.lineTo(a,r+t),c.stroke()}c.strokeStyle=this.colorAxis,c.strokeRect(h,r,i,n)}if(this.style===s.STYLE.DOTSIZE&&(c.strokeStyle=this.colorAxis,c.fillStyle=this.colorDot,c.beginPath(),c.moveTo(h,r),c.lineTo(a,r),c.lineTo(a-i+e,d),c.lineTo(h,d),c.closePath(),c.fill(),c.stroke()),this.style===s.STYLE.DOTCOLOR||this.style===s.STYLE.DOTSIZE){var y=5,b=new f(this.valueMin,this.valueMax,(this.valueMax-this.valueMin)/5,!0);for(b.start(),b.getCurrent()0?this.yMin:this.yMax,o=this._convert3Dto2D(new l(x,r,this.zMin)),Math.cos(2*_)>0?(g.textAlign="center",g.textBaseline="top",o.y+=b):Math.sin(2*_)<0?(g.textAlign="right",g.textBaseline="middle"):(g.textAlign="left",g.textBaseline="middle"),g.fillStyle=this.colorAxis,g.fillText(" "+this.xValueLabel(i.getCurrent())+" ",o.x,o.y),i.next()}for(g.lineWidth=1,s=void 0===this.defaultYStep,i=new f(this.yMin,this.yMax,this.yStep,s),i.start(),i.getCurrent()0?this.xMin:this.xMax,o=this._convert3Dto2D(new l(n,i.getCurrent(),this.zMin)),Math.cos(2*_)<0?(g.textAlign="center",g.textBaseline="top",o.y+=b):Math.sin(2*_)>0?(g.textAlign="right",g.textBaseline="middle"):(g.textAlign="left",g.textBaseline="middle"),g.fillStyle=this.colorAxis,g.fillText(" "+this.yValueLabel(i.getCurrent())+" ",o.x,o.y),i.next();for(g.lineWidth=1,s=void 0===this.defaultZStep,i=new f(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 l(n,r,i.getCurrent())),g.strokeStyle=this.colorAxis,g.beginPath(),g.moveTo(t.x,t.y),g.lineTo(t.x-b,t.y),g.stroke(),g.textAlign="right",g.textBaseline="middle",g.fillStyle=this.colorAxis,g.fillText(this.zValueLabel(i.getCurrent())+" ",t.x-5,t.y),i.next();g.lineWidth=1,t=this._convert3Dto2D(new l(n,r,this.zMin)),e=this._convert3Dto2D(new l(n,r,this.zMax)),g.strokeStyle=this.colorAxis,g.beginPath(),g.moveTo(t.x,t.y),g.lineTo(e.x,e.y),g.stroke(),g.lineWidth=1,p=this._convert3Dto2D(new l(this.xMin,this.yMin,this.zMin)),u=this._convert3Dto2D(new l(this.xMax,this.yMin,this.zMin)),g.strokeStyle=this.colorAxis,g.beginPath(),g.moveTo(p.x,p.y),g.lineTo(u.x,u.y),g.stroke(),p=this._convert3Dto2D(new l(this.xMin,this.yMax,this.zMin)),u=this._convert3Dto2D(new l(this.xMax,this.yMax,this.zMin)),g.strokeStyle=this.colorAxis,g.beginPath(),g.moveTo(p.x,p.y),g.lineTo(u.x,u.y),g.stroke(),g.lineWidth=1,t=this._convert3Dto2D(new l(this.xMin,this.yMin,this.zMin)),e=this._convert3Dto2D(new l(this.xMin,this.yMax,this.zMin)),g.strokeStyle=this.colorAxis,g.beginPath(),g.moveTo(t.x,t.y),g.lineTo(e.x,e.y),g.stroke(),t=this._convert3Dto2D(new l(this.xMax,this.yMin,this.zMin)),e=this._convert3Dto2D(new l(this.xMax,this.yMax,this.zMin)),g.strokeStyle=this.colorAxis,g.beginPath(),g.moveTo(t.x,t.y),g.lineTo(e.x,e.y),g.stroke();var w=this.xLabel;w.length>0&&(c=.1/this.scale.y,n=(this.xMin+this.xMax)/2,r=Math.cos(_)>0?this.yMin-c:this.yMax+c,o=this._convert3Dto2D(new l(n,r,this.zMin)),Math.cos(2*_)>0?(g.textAlign="center",g.textBaseline="top"):Math.sin(2*_)<0?(g.textAlign="right",g.textBaseline="middle"):(g.textAlign="left",g.textBaseline="middle"),g.fillStyle=this.colorAxis,g.fillText(w,o.x,o.y));var S=this.yLabel;S.length>0&&(d=.1/this.scale.x,n=Math.sin(_)>0?this.xMin-d:this.xMax+d,r=(this.yMin+this.yMax)/2,o=this._convert3Dto2D(new l(n,r,this.zMin)),Math.cos(2*_)<0?(g.textAlign="center",g.textBaseline="top"):Math.sin(2*_)>0?(g.textAlign="right",g.textBaseline="middle"):(g.textAlign="left",g.textBaseline="middle"),g.fillStyle=this.colorAxis,g.fillText(S,o.x,o.y));var M=this.zLabel;M.length>0&&(h=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 l(n,r,a)),g.textAlign="right",g.textBaseline="middle",g.fillStyle=this.colorAxis,g.fillText(M,o.x-h,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,h,d,c,p,u,m,f=this.frame.canvas,g=f.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),h=a):(u=1,a=this._hsv2rgb(c,p,u),h=this.colorAxis)):(a="gray",h=this.colorAxis),d=.5,g.lineWidth=d,g.fillStyle=a,g.strokeStyle=h,g.beginPath(),g.moveTo(t.screen.x,t.screen.y),g.lineTo(e.screen.x,e.screen.y),g.lineTo(o.screen.x,o.screen.y),g.lineTo(i.screen.x,i.screen.y),g.closePath(),g.fill(),g.stroke()}}else for(n=0;np&&(p=0);var u,m,f;this.style===s.STYLE.DOTCOLOR?(u=240*(1-(d.point.value-this.valueMin)*this.scale.value),m=this._hsv2rgb(u,1,1),f=this._hsv2rgb(u,1,.8)):this.style===s.STYLE.DOTSIZE?(m=this.colorDot,f=this.colorDotBorder):(u=240*(1-(d.point.z-this.zMin)*this.scale.z/this.verticalRatio),m=this._hsv2rgb(u,1,1),f=this._hsv2rgb(u,1,.8)),i.lineWidth=1,i.strokeStyle=f,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=o(t),this.startMouseY=n(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)},d.addEventListener(document,"mousemove",e.onmousemove),d.addEventListener(document,"mouseup",e.onmouseup),d.preventDefault(t)}},s.prototype._onMouseMove=function(t){t=t||window.event;var e=parseFloat(o(t))-this.startMouseX,i=parseFloat(n(t))-this.startMouseY,s=this.startArmRotation.horizontal+e/200,r=this.startArmRotation.vertical+i/200,a=4,h=Math.sin(a/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 c(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 d=n.surfaces;if(d)for(var l=d.length-1;l>=0;l--){var p=d[l],u=p.corners,m=[u[0].screen,u[1].screen,u[2].screen],f=[u[2].screen,u[3].screen,u[0].screen];if(this._insideTriangle(h,m)||this._insideTriangle(h,f))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)}}},t.exports=s},function(t,e,i){function s(){this.armLocation=new o,this.armRotation={},this.armRotation.horizontal=0,this.armRotation.vertical=0,this.armLength=1.7,this.cameraLocation=new o,this.cameraRotation=new o(.5*Math.PI,0,0),this.calculateCameraOrientation()}var o=i(10);s.prototype.setArmLocation=function(t,e,i){this.armLocation.x=t,this.armLocation.y=e,this.armLocation.z=i,this.calculateCameraOrientation()},s.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()},s.prototype.getArmRotation=function(){var t={};return t.horizontal=this.armRotation.horizontal,t.vertical=this.armRotation.vertical,t},s.prototype.setArmLength=function(t){void 0!==t&&(this.armLength=t,this.armLength<.71&&(this.armLength=.71),this.armLength>5&&(this.armLength=5),this.calculateCameraOrientation())},s.prototype.getArmLength=function(){return this.armLength},s.prototype.getCameraLocation=function(){return this.cameraLocation},s.prototype.getCameraRotation=function(){return this.cameraRotation},s.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=s},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,h){if(!(this instanceof s))throw new SyntaxError("Constructor must be called with the new operator");if(!(Array.isArray(i)||i instanceof n||i instanceof r)&&i instanceof Object){var u=h;h=i,i=u}var m=this;this.defaultOptions={start:null,end:null,autoResize:!0,orientation:"bottom",width:null,height:null,maxHeight:null,minHeight:null},this.options=o.deepExtend({},this.defaultOptions),this._create(t),this.components=[],this.body={dom:this.dom,domProps:this.props,emitter:{on:this.on.bind(this),off:this.off.bind(this),emit:this.emit.bind(this)},hiddenDates:[],util:{getScale:function(){return m.timeAxis.step.scale},getStep:function(){return m.timeAxis.step.step},toScreen:m._toScreen.bind(m),toGlobalScreen:m._toGlobalScreen.bind(m),toTime:m._toTime.bind(m),toGlobalTime:m._toGlobalTime.bind(m)}},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.currentTime=new l(this.body),this.components.push(this.currentTime),this.customTime=new c(this.body),this.components.push(this.customTime),this.itemSet=new p(this.body),this.components.push(this.itemSet),this.itemsData=null,this.groupsData=null,h&&this.setOptions(h),i&&this.setGroups(i),e?this.setItems(e):this._redraw()}var o=(i(56),i(45),i(1)),n=i(3),r=i(4),a=i(17),h=i(46),d=i(30),l=i(21),c=i(22),p=i(27);s.prototype=new h,s.prototype.redraw=function(){this.itemSet&&this.itemSet.markDirty({refreshItems:!0}),this._redraw()},s.prototype.setItems=function(t){var e,i=null==this.itemsData;if(e=t?t instanceof n||t instanceof r?t:new n(t,{type:{start:"Date",end:"Date"}}):null,this.itemsData=e,this.itemSet&&this.itemSet.setItems(e),i)if(void 0!=this.options.start||void 0!=this.options.end){if(void 0==this.options.start||void 0==this.options.end)var s=this._getDataRange();var o=void 0!=this.options.start?this.options.start:s.start,a=void 0!=this.options.end?this.options.end:s.end;this.setWindow(o,a,{animate:!1})}else this.fit({animate:!1})},s.prototype.setGroups=function(t){var e;e=t?t instanceof n||t instanceof r?t:new n(t):null,this.groupsData=e,this.itemSet.setGroups(e)},s.prototype.setSelection=function(t,e){this.itemSet&&this.itemSet.setSelection(t),e&&e.focus&&this.focus(t,e)},s.prototype.getSelection=function(){return this.itemSet&&this.itemSet.getSelection()||[]},s.prototype.focus=function(t,e){if(this.itemsData&&void 0!=t){var i=Array.isArray(t)?t:[t],s=this.itemsData.getDataSet().get(i,{type:{start:"Date",end:"Date"}}),o=null,n=null;if(s.forEach(function(t){var e=t.start.valueOf(),i="end"in t?t.end.valueOf():t.start.valueOf();(null===o||o>e)&&(o=e),(null===n||i>n)&&(n=i)}),null!==o&&null!==n){var r=(o+n)/2,a=Math.max(this.range.end-this.range.start,1.1*(n-o)),h=e&&void 0!==e.animate?e.animate:!0;this.range.setRange(r-a/2,r+a/2,h)}}},s.prototype.getItemRange=function(){var t=this.itemsData.getDataSet(),e=null,i=null;if(t){var s=t.min("start");e=s?o.convert(s.start,"Date").valueOf():null;var n=t.max("start");n&&(i=o.convert(n.start,"Date").valueOf());var r=t.max("end");r&&(i=null==i?o.convert(r.end,"Date").valueOf():Math.max(i,o.convert(r.end,"Date").valueOf()))}return{min:null!=e?new Date(e):null,max:null!=i?new Date(i):null}},t.exports=s},function(t,e,i){function s(t,e,i,s){if(!(Array.isArray(i)||i instanceof n)&&i instanceof Object){var r=s;s=i,i=r}var h=this;this.defaultOptions={start:null,end:null,autoResize:!0,orientation:"bottom",width:null,height:null,maxHeight:null,minHeight:null},this.options=o.deepExtend({},this.defaultOptions),this._create(t),this.components=[],this.body={dom:this.dom,domProps:this.props,emitter:{on:this.on.bind(this),off:this.off.bind(this),emit:this.emit.bind(this)},hiddenDates:[],util:{toScreen:h._toScreen.bind(h),toGlobalScreen:h._toGlobalScreen.bind(h),toTime:h._toTime.bind(h),toGlobalTime:h._toGlobalTime.bind(h)}},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.currentTime=new l(this.body),this.components.push(this.currentTime),this.customTime=new c(this.body),this.components.push(this.customTime),this.linegraph=new p(this.body),this.components.push(this.linegraph),this.itemsData=null,this.groupsData=null,s&&this.setOptions(s),i&&this.setGroups(i),e?this.setItems(e):this._redraw()}var o=(i(56),i(45),i(1)),n=i(3),r=i(4),a=i(17),h=i(46),d=i(30),l=i(21),c=i(22),p=i(29);s.prototype=new h,s.prototype.setItems=function(t){var e,i=null==this.itemsData;if(e=t?t instanceof n||t instanceof r?t:new n(t,{type:{start:"Date",end:"Date"}}):null,this.itemsData=e,this.linegraph&&this.linegraph.setItems(e),i)if(void 0!=this.options.start||void 0!=this.options.end){var s=void 0!=this.options.start?this.options.start:null,o=void 0!=this.options.end?this.options.end:null;this.setWindow(s,o,{animate:!1})}else this.fit({animate:!1})},s.prototype.setGroups=function(t){var e;e=t?t instanceof n||t instanceof r?t:new n(t):null,this.groupsData=e,this.linegraph.setGroups(e)},s.prototype.getLegend=function(t,e,i){return void 0===e&&(e=15),void 0===i&&(i=15),void 0!==this.linegraph.groups[t]?this.linegraph.groups[t].getLegend(e,i):"cannot find group:"+t},s.prototype.isGroupVisible=function(t){return void 0!==this.linegraph.groups[t]?this.linegraph.groups[t].visible&&(void 0===this.linegraph.options.groups.visibility[t]||1==this.linegraph.options.groups.visibility[t]):!1},s.prototype.getItemRange=function(){var t=null,e=null;for(var i in this.linegraph.groups)if(this.linegraph.groups.hasOwnProperty(i)&&1==this.linegraph.groups[i].visible)for(var s=0;sr?r:t,e=null==e?r:r>e?r:e}return{min:null!=t?new Date(t):null,max:null!=e?new Date(e):null}},t.exports=s},function(t,e,i){var s=i(44);e.convertHiddenOptions=function(t,e){if(t.hiddenDates=[],e&&1==Array.isArray(e)){for(var i=0;i=4*a){var p=0,u=n.clone();switch(i[h].repeat){case"daily":d.day()!=l.day()&&(p=1),d.dayOfYear(o.dayOfYear()),d.year(o.year()),d.subtract(7,"days"),l.dayOfYear(o.dayOfYear()),l.year(o.year()),l.subtract(7-p,"days"),u.add(1,"weeks");break;case"weekly":var m=l.diff(d,"days"),f=d.day();d.date(o.date()),d.month(o.month()),d.year(o.year()),l=d.clone(),d.day(f),l.day(f),l.add(m,"days"),d.subtract(1,"weeks"),l.subtract(1,"weeks"),u.add(1,"weeks");break;case"monthly":d.month()!=l.month()&&(p=1),d.month(o.month()),d.year(o.year()),d.subtract(1,"months"),l.month(o.month()),l.year(o.year()),l.subtract(1,"months"),l.add(p,"months"),u.add(1,"months");break;case"yearly":d.year()!=l.year()&&(p=1),d.year(o.year()),d.subtract(1,"years"),l.year(o.year()),l.subtract(1,"years"),l.add(p,"years"),u.add(1,"years");break;default:return void console.log("Wrong repeat format, allowed are: daily, weekly, monthly, yearly. Given:",i[h].repeat)}for(;u>d;)switch(t.hiddenDates.push({start:d.valueOf(),end:l.valueOf()}),i[h].repeat){case"daily":d.add(1,"days"),l.add(1,"days");break;case"weekly":d.add(1,"weeks"),l.add(1,"weeks");break;case"monthly":d.add(1,"months"),l.add(1,"months");break;case"yearly":d.add(1,"y"),l.add(1,"y");break;default:return void console.log("Wrong repeat format, allowed are: daily, weekly, monthly, yearly. Given:",i[h].repeat)}t.hiddenDates.push({start:d.valueOf(),end:l.valueOf()})}}e.removeDuplicates(t);var g=e.isHidden(t.range.start,t.hiddenDates),v=e.isHidden(t.range.end,t.hiddenDates),y=t.range.start,b=t.range.end;1==g.hidden&&(y=1==t.range.startToFront?g.startDate-1:g.endDate+1),1==v.hidden&&(b=1==t.range.endToFront?v.startDate-1:v.endDate+1),(1==g.hidden||1==v.hidden)&&t.range._applyRange(y,b)}},e.removeDuplicates=function(t){for(var e=t.hiddenDates,i=[],s=0;s=e[s].start&&e[o].end<=e[s].end?e[o].remove=!0:e[o].start>=e[s].start&&e[o].start<=e[s].end?(e[s].end=e[o].end,e[o].remove=!0):e[o].end>=e[s].start&&e[o].end<=e[s].end&&(e[s].start=e[o].start,e[o].remove=!0));for(var s=0;s=r&&a>o){i=!0;break}}if(1==i&&o=e&&i>r&&(s+=r-n)}return s},e.correctTimeForHidden=function(t,i,o){return o=s(o).toDate().valueOf(),o-=e.getHiddenDurationBefore(t,i,o)},e.getHiddenDurationBefore=function(t,e,i){var o=0;i=s(i).toDate().valueOf();for(var n=0;n=e.start&&a=a&&(o+=a-r)}return o},e.getAccumulatedHiddenDuration=function(t,e,i){for(var s=0,o=0,n=e.start,r=0;r=e.start&&h=i)break;s+=h-a}}return s},e.snapAwayFromHidden=function(t,i,s,o){var n=e.isHidden(i,t);return 1==n.hidden?0>s?1==o?n.startDate-(n.endDate-i)-1:n.startDate-1:1==o?n.endDate+(i-n.startDate)+1:n.endDate+1:i},e.isHidden=function(t,e){for(var i=0;i=s&&o>t)return{hidden:!0,startDate:s,endDate:o}}return{hidden:!1,startDate:s,endDate:o}}},function(t){function e(t,e,i,s,o,n){this.current=0,this.autoScale=!0,this.stepIndex=0,this.step=1,this.scale=1,this.marginStart,this.marginEnd,this.deadSpace=0,this.majorSteps=[1,2,5,10],this.minorSteps=[.25,.5,1,2],this.alignZeros=n,this.setRange(t,e,i,s,o)}e.prototype.setRange=function(t,e,i,s,o){this._start=void 0===o.min?t:o.min,this._end=void 0===o.max?e:o.max,this._start==this._end&&(this._start-=.75,this._end+=1),1==this.autoScale&&this.setMinimumStep(i,s),this.setFirst(o)},e.prototype.setMinimumStep=function(t,e){var i=this._end-this._start,s=1.2*i,o=t*(s/e),n=Math.round(Math.log(s)/Math.LN10),r=-1,a=Math.pow(10,n),h=0;0>n&&(h=n);for(var d=!1,l=h;Math.abs(l)<=Math.abs(n);l++){a=Math.pow(10,l);for(var c=0;c=o){d=!0,r=c;break}}if(1==d)break}this.stepIndex=r,this.scale=a,this.step=a*this.minorSteps[r]},e.prototype.setFirst=function(t){void 0===t&&(t={});var e=void 0===t.min?this._start-2*this.scale*this.minorSteps[this.stepIndex]:t.min,i=void 0===t.max?this._end+this.scale*this.minorSteps[this.stepIndex]:t.max;this.marginEnd=void 0===t.max?this.roundToMinor(i):t.max,this.marginStart=void 0===t.min?this.roundToMinor(e):t.min,1==this.alignZeros&&(this.marginEnd-this.marginStart)%this.step!=0&&(this.marginEnd+=this.marginEnd%this.step),this.deadSpace=this.roundToMinor(i)-i+this.roundToMinor(e)-e,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(t){var e=Math.abs(this.current)0;s--){if("0"!=i[s]){if("."==i[s]||","==i[s]){i=i.slice(0,s);break}break}i=i.slice(0,s)}}else{var o="",n=i.indexOf("e");if(-1!=n&&(o=i.slice(n),i=i.slice(0,n)),n=Math.max(i.indexOf(","),i.indexOf(".")),-1===n?(0!==t&&(i+="."),n=i.length+t):0!==t&&(n+=t+1),n>i.length)for(var r=n-i.length;r>0;r--)i+="0";else i=i.slice(0,n);i+=o}return i},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(-3,"days").valueOf(),this.end=i.clone().add(4,"days").valueOf(),this.body=t,this.deltaDifference=0,this.scaleOffset=0,this.startToFront=!1,this.endToFront=!0,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.animateTimer=null,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(47),h=i(44),d=i(20),l=i(15);s.prototype=new d,s.prototype.setOptions=function(t){if(t){var e=["direction","min","max","zoomMin","zoomMax","moveable","zoomable","activate","hiddenDates"];r.selectiveExtend(e,this.options,t),("start"in t||"end"in t)&&this.setRange(t.start,t.end)}},s.prototype.setRange=function(t,e,i,s){s!==!0&&(s=!1);var o=void 0!=t?r.convert(t,"Date").valueOf():null,n=void 0!=e?r.convert(e,"Date").valueOf():null;if(this._cancelAnimation(),i){var a=this,h=this.start,d=this.end,c="number"==typeof i?i:500,p=(new Date).valueOf(),u=!1,m=function(){if(!a.props.touch.dragging){var t=(new Date).valueOf(),e=t-p,i=e>c,g=i||null===o?o:r.easeInOutQuad(e,h,o,c),v=i||null===n?n:r.easeInOutQuad(e,d,n,c);f=a._applyRange(g,v),l.updateHiddenDates(a.body,a.options.hiddenDates),u=u||f,f&&a.body.emitter.emit("rangechange",{start:new Date(a.start),end:new Date(a.end),byUser:s}),i?u&&a.body.emitter.emit("rangechanged",{start:new Date(a.start),end:new Date(a.end),byUser:s}):a.animateTimer=setTimeout(m,20)}};return m()}var f=this._applyRange(o,n);if(l.updateHiddenDates(this.body,this.options.hiddenDates),f){var g={start:new Date(this.start),end:new Date(this.end),byUser:s};this.body.emitter.emit("rangechange",g),this.body.emitter.emit("rangechanged",g)}},s.prototype._cancelAnimation=function(){this.animateTimer&&(clearTimeout(this.animateTimer),this.animateTimer=null)},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&&od&&(d=0),o-s>d&&(this.end-this.start===d&&sthis.end?(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 s>=this.start&&s<=this.end||o>=this.start&&o<=this.end||this.start>=s&&this.start<=o||this.end>=s&&this.end<=o||this.body.emitter.emit("checkRangedItems"),this.start=s,this.end=o,l},s.prototype.getRange=function(){return{start:this.start,end:this.end}},s.prototype.conversion=function(t,e){return s.conversion(this.start,this.end,t,e)},s.conversion=function(t,e,i,s){return void 0===s&&(s=0),0!=i&&e-t!=0?{offset:t,scale:i/(e-t-s)}:{offset:0,scale:1}},s.prototype._onDragStart=function(){this.deltaDifference=0,this.previousDelta=0,this.options.moveable&&this.props.touch.allowDragging&&(this.props.touch.start=this.start,this.props.touch.end=this.end,this.props.touch.dragging=!0,this.body.dom.root&&(this.body.dom.root.style.cursor="move"))},s.prototype._onDrag=function(t){if(this.options.moveable&&this.props.touch.allowDragging){var e=this.options.direction;o(e);var i="horizontal"==e?t.gesture.deltaX:t.gesture.deltaY;i-=this.deltaDifference;var s=this.props.touch.end-this.props.touch.start,n=l.getHiddenDurationBetween(this.body.hiddenDates,this.start,this.end);s-=n;var r="horizontal"==e?this.body.domProps.center.width:this.body.domProps.center.height,a=-i/r*s,h=this.props.touch.start+a,d=this.props.touch.end+a,c=l.snapAwayFromHidden(this.body.hiddenDates,h,this.previousDelta-i,!0),p=l.snapAwayFromHidden(this.body.hiddenDates,d,this.previousDelta-i,!0);if(c!=h||p!=d)return this.deltaDifference+=i,this.props.touch.start=c,this.props.touch.end=p,void this._onDrag(t);this.previousDelta=i,this._applyRange(h,d),this.body.emitter.emit("rangechange",{start:new Date(this.start),end:new Date(this.end),byUser:!0})}},s.prototype._onDragEnd=function(){this.options.moveable&&this.props.touch.allowDragging&&(this.props.touch.dragging=!1,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),byUser:!0}))},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,e)}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,this.scaleOffset=0,this.deltaDifference=0},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+this.scaleOffset),i=this._pointerToDate(this.props.touch.center),s=l.getHiddenDurationBetween(this.body.hiddenDates,this.start,this.end),o=l.getHiddenDurationBefore(this.body.hiddenDates,this,i),r=s-o,a=i-o+(this.props.touch.start-(i-o))*e,h=i+r+(this.props.touch.end-(i+r))*e;this.startToFront=1-e>0?!1:!0,this.endToFront=e-1>0?!1:!0;var d=l.snapAwayFromHidden(this.body.hiddenDates,a,1-e,!0),c=l.snapAwayFromHidden(this.body.hiddenDates,h,e-1,!0);(d!=a||c!=h)&&(this.props.touch.start=d,this.props.touch.end=c,this.scaleOffset=1-t.gesture.scale,a=d,h=c),this.setRange(a,h,!1,!0),this.startToFront=!1,this.endToFront=!0}},s.prototype._pointerToDate=function(t){var e,i=this.options.direction;if(o(i),"horizontal"==i)return this.body.util.toTime(t.x).valueOf();var s=this.body.domProps.center.height;return e=this.conversion(s),t.y/e.scale+e.offset},s.prototype.zoom=function(t,e,i){null==e&&(e=(this.start+this.end)/2);var s=l.getHiddenDurationBetween(this.body.hiddenDates,this.start,this.end),o=l.getHiddenDurationBefore(this.body.hiddenDates,this,e),n=s-o,r=e-o+(this.start-(e-o))*t,a=e+n+(this.end-(e+n))*t;this.startToFront=i>0?!1:!0,this.endToFront=-i>0?!1:!0;var h=l.snapAwayFromHidden(this.body.hiddenDates,r,i,!0),d=l.snapAwayFromHidden(this.body.hiddenDates,a,-i,!0);(h!=r||d!=a)&&(r=h,a=d),this.setRange(r,a,!1,!0),this.startToFront=!1,this.endToFront=!0},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(r.stack&&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&&l.stack&&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,i){var s,o,n;for(s=0,o=t.length;o>s;s++)if(void 0!==t[s].data.subgroup){n=e.axis;for(var r in i)i.hasOwnProperty(r)&&1==i[r].visible&&i[r].indexe.left&&t.top-s.vertical+ie.top}},function(t,e,i){function s(t,e,i,o){this.current=new Date,this._start=new Date,this._end=new Date,this.autoScale=!0,this.scale="day",this.step=1,this.setRange(t,e,i),this.switchedDay=!1,this.switchedMonth=!1,this.switchedYear=!1,this.hiddenDates=o,void 0===o&&(this.hiddenDates=[]),this.format=s.FORMAT}var o=i(44),n=i(15),r=i(1);s.FORMAT={minorLabels:{millisecond:"SSS",second:"s",minute:"HH:mm",hour:"HH:mm",weekday:"ddd D",day:"D",month:"MMM",year:"YYYY"},majorLabels:{millisecond:"HH:mm:ss",second:"D MMMM HH:mm",minute:"ddd D MMMM",hour:"ddd D MMMM",weekday:"MMMM YYYY",day:"MMMM YYYY",month:"YYYY",year:""}},s.prototype.setFormat=function(t){var e=r.deepExtend({},s.FORMAT);this.format=r.deepExtend(e,t)},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"year":this.current.setFullYear(this.step*Math.floor(this.current.getFullYear()/this.step)),this.current.setMonth(0);case"month":this.current.setDate(1);case"day":case"weekday":this.current.setHours(0);case"hour":this.current.setMinutes(0);case"minute":this.current.setSeconds(0);case"second":this.current.setMilliseconds(0)}if(1!=this.step)switch(this.scale){case"millisecond":this.current.setMilliseconds(this.current.getMilliseconds()-this.current.getMilliseconds()%this.step);break;case"second":this.current.setSeconds(this.current.getSeconds()-this.current.getSeconds()%this.step); -break;case"minute":this.current.setMinutes(this.current.getMinutes()-this.current.getMinutes()%this.step);break;case"hour":this.current.setHours(this.current.getHours()-this.current.getHours()%this.step);break;case"weekday":case"day":this.current.setDate(this.current.getDate()-1-(this.current.getDate()-1)%this.step+1);break;case"month":this.current.setMonth(this.current.getMonth()-this.current.getMonth()%this.step);break;case"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"millisecond":this.current=new Date(this.current.valueOf()+this.step);break;case"second":this.current=new Date(this.current.valueOf()+1e3*this.step);break;case"minute":this.current=new Date(this.current.valueOf()+1e3*this.step*60);break;case"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"weekday":case"day":this.current.setDate(this.current.getDate()+this.step);break;case"month":this.current.setMonth(this.current.getMonth()+this.step);break;case"year":this.current.setFullYear(this.current.getFullYear()+this.step)}else switch(this.scale){case"millisecond":this.current=new Date(this.current.valueOf()+this.step);break;case"second":this.current.setSeconds(this.current.getSeconds()+this.step);break;case"minute":this.current.setMinutes(this.current.getMinutes()+this.step);break;case"hour":this.current.setHours(this.current.getHours()+this.step);break;case"weekday":case"day":this.current.setDate(this.current.getDate()+this.step);break;case"month":this.current.setMonth(this.current.getMonth()+this.step);break;case"year":this.current.setFullYear(this.current.getFullYear()+this.step)}if(1!=this.step)switch(this.scale){case"millisecond":this.current.getMilliseconds()0?t.step:1,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,s=864e5,o=36e5,n=6e4,r=1e3,a=1;1e3*e>t&&(this.scale="year",this.step=1e3),500*e>t&&(this.scale="year",this.step=500),100*e>t&&(this.scale="year",this.step=100),50*e>t&&(this.scale="year",this.step=50),10*e>t&&(this.scale="year",this.step=10),5*e>t&&(this.scale="year",this.step=5),e>t&&(this.scale="year",this.step=1),3*i>t&&(this.scale="month",this.step=3),i>t&&(this.scale="month",this.step=1),5*s>t&&(this.scale="day",this.step=5),2*s>t&&(this.scale="day",this.step=2),s>t&&(this.scale="day",this.step=1),s/2>t&&(this.scale="weekday",this.step=1),4*o>t&&(this.scale="hour",this.step=4),o>t&&(this.scale="hour",this.step=1),15*n>t&&(this.scale="minute",this.step=15),10*n>t&&(this.scale="minute",this.step=10),5*n>t&&(this.scale="minute",this.step=5),n>t&&(this.scale="minute",this.step=1),15*r>t&&(this.scale="second",this.step=15),10*r>t&&(this.scale="second",this.step=10),5*r>t&&(this.scale="second",this.step=5),r>t&&(this.scale="second",this.step=1),200*a>t&&(this.scale="millisecond",this.step=200),100*a>t&&(this.scale="millisecond",this.step=100),50*a>t&&(this.scale="millisecond",this.step=50),10*a>t&&(this.scale="millisecond",this.step=10),5*a>t&&(this.scale="millisecond",this.step=5),a>t&&(this.scale="millisecond",this.step=1)}},s.snap=function(t,e,i){var s=new Date(t.valueOf());if("year"==e){var o=s.getFullYear()+Math.round(s.getMonth()/12);s.setFullYear(Math.round(o/i)*i),s.setMonth(0),s.setDate(0),s.setHours(0),s.setMinutes(0),s.setSeconds(0),s.setMilliseconds(0)}else if("month"==e)s.getDate()>15?(s.setDate(1),s.setMonth(s.getMonth()+1)):s.setDate(1),s.setHours(0),s.setMinutes(0),s.setSeconds(0),s.setMilliseconds(0);else if("day"==e){switch(i){case 5:case 2:s.setHours(24*Math.round(s.getHours()/24));break;default:s.setHours(12*Math.round(s.getHours()/12))}s.setMinutes(0),s.setSeconds(0),s.setMilliseconds(0)}else if("weekday"==e){switch(i){case 5:case 2:s.setHours(12*Math.round(s.getHours()/12));break;default:s.setHours(6*Math.round(s.getHours()/6))}s.setMinutes(0),s.setSeconds(0),s.setMilliseconds(0)}else if("hour"==e){switch(i){case 4:s.setMinutes(60*Math.round(s.getMinutes()/60));break;default:s.setMinutes(30*Math.round(s.getMinutes()/30))}s.setSeconds(0),s.setMilliseconds(0)}else if("minute"==e){switch(i){case 15:case 10:s.setMinutes(5*Math.round(s.getMinutes()/5)),s.setSeconds(0);break;case 5:s.setSeconds(60*Math.round(s.getSeconds()/60));break;default:s.setSeconds(30*Math.round(s.getSeconds()/30))}s.setMilliseconds(0)}else if("second"==e)switch(i){case 15:case 10:s.setSeconds(5*Math.round(s.getSeconds()/5)),s.setMilliseconds(0);break;case 5:s.setMilliseconds(1e3*Math.round(s.getMilliseconds()/1e3));break;default:s.setMilliseconds(500*Math.round(s.getMilliseconds()/500))}else if("millisecond"==e){var n=i>5?i/2:1;s.setMilliseconds(Math.round(s.getMilliseconds()/n)*n)}return s},s.prototype.isMajor=function(){if(1==this.switchedYear)switch(this.switchedYear=!1,this.scale){case"year":case"month":case"weekday":case"day":case"hour":case"minute":case"second":case"millisecond":return!0;default:return!1}else if(1==this.switchedMonth)switch(this.switchedMonth=!1,this.scale){case"weekday":case"day":case"hour":case"minute":case"second":case"millisecond":return!0;default:return!1}else if(1==this.switchedDay)switch(this.switchedDay=!1,this.scale){case"millisecond":case"second":case"minute":case"hour":return!0;default:return!1}switch(this.scale){case"millisecond":return 0==this.current.getMilliseconds();case"second":return 0==this.current.getSeconds();case"minute":return 0==this.current.getHours()&&0==this.current.getMinutes();case"hour":return 0==this.current.getHours();case"weekday":case"day":return 1==this.current.getDate();case"month":return 0==this.current.getMonth();case"year":return!1;default:return!1}},s.prototype.getLabelMinor=function(t){void 0==t&&(t=this.current);var e=this.format.minorLabels[this.scale];return e&&e.length>0?o(t).format(e):""},s.prototype.getLabelMajor=function(t){void 0==t&&(t=this.current);var e=this.format.majorLabels[this.scale];return e&&e.length>0?o(t).format(e):""},s.prototype.getClassName=function(){function t(t){return t/h%2==0?" even":" odd"}function e(t){return t.isSame(new Date,"day")?" today":t.isSame(o().add(1,"day"),"day")?" tomorrow":t.isSame(o().add(-1,"day"),"day")?" yesterday":""}function i(t){return t.isSame(new Date,"week")?" current-week":""}function s(t){return t.isSame(new Date,"month")?" current-month":""}function n(t){return t.isSame(new Date,"year")?" current-year":""}var r=o(this.current),a=r.locale?r.locale("en"):r.lang("en"),h=this.step;switch(this.scale){case"millisecond":return t(a.milliseconds()).trim();case"second":return t(a.seconds()).trim();case"minute":return t(a.minutes()).trim();case"hour":var d=a.hours();return 4==this.step&&(d=d+"-"+(d+4)),d+"h"+e(a)+t(a.hours());case"weekday":return a.format("dddd").toLowerCase()+e(a)+i(a)+t(a.date());case"day":var l=a.date(),c=a.format("MMMM").toLowerCase();return"day"+l+" "+c+s(a)+t(l-1);case"month":return a.format("MMMM").toLowerCase()+s(a)+t(a.month());case"year":var p=a.year();return"year"+p+n(a)+t(p);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,locales:a,locale:"en"},this.options=o.extend({},this.defaultOptions),this.offset=0,this._create(),this.setOptions(e)}var o=i(1),n=i(20),r=i(44),a=i(48);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","locale","locales"],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((new Date).valueOf()+this.offset),i=this.body.util.toScreen(e),s=this.options.locales[this.options.locale],o=s.current+" "+s.time+": "+r(e).format("dddd, MMMM Do YYYY, H:mm:ss");o=o.charAt(0).toUpperCase()+o.substring(1),this.bar.style.left=i+"px",this.bar.title=o}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)},s.prototype.setCurrentTime=function(t){var e=o.convert(t,"Date").valueOf(),i=(new Date).valueOf();this.offset=e-i,this.redraw()},s.prototype.getCurrentTime=function(){return new Date((new Date).valueOf()+this.offset)},t.exports=s},function(t,e,i){function s(t,e){this.body=t,this.defaultOptions={showCustomTime:!1,locales:h,locale:"en"},this.options=n.extend({},this.defaultOptions),this.customTime=new Date,this.eventParams={},this._create(),this.setOptions(e)}var o=i(45),n=i(1),r=i(20),a=i(44),h=i(48);s.prototype=new r,s.prototype.setOptions=function(t){t&&n.selectiveExtend(["showCustomTime","locale","locales"],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),i=this.options.locales[this.options.locale],s=i.time+": "+a(this.customTime).format("dddd, MMMM Do YYYY, H:mm:ss");s=s.charAt(0).toUpperCase()+s.substring(1),this.bar.style.left=e+"px",this.bar.title=s}else this.bar.parentNode&&this.bar.parentNode.removeChild(this.bar);return!1},s.prototype.setCustomTime=function(t){this.customTime=n.convert(t,"Date"),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,s){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,alignZeros:!0,customRange:{left:{min:void 0,max:void 0},right:{min:void 0,max:void 0}},title:{left:{text:void 0},right:{text:void 0}},format:{left:{decimals:void 0},right:{decimals:void 0}}},this.linegraphOptions=s,this.linegraphSVG=i,this.props={},this.DOMelements={lines:{},labels:{},title:{}},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.hidden=!1,this.stepPixels=25,this.stepPixelsForced=25,this.zeroCrossing=-1,this.lineOffset=0,this.master=!0,this.svgElements={},this.iconsRemoved=!1,this.groups={},this.amountOfGroups=0,this._create();var n=this;this.body.emitter.on("verticalDrag",function(){n.dom.lineContainer.style.top=n.body.domProps.scrollTop+"px"})}var o=i(1),n=i(2),r=i(20),a=i(16);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","customRange","title","format","alignZeros"];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.dom.lineContainer.style.position="relative",this.svg=document.createElementNS("http://www.w3.org/2000/svg","svg"),this.svg.style.position="absolute",this.svg.style.top="0px",this.svg.style.height="100%",this.svg.style.width="100%",this.svg.style.display="block",this.dom.frame.appendChild(this.svg)},s.prototype._redrawGroupIcons=function(){n.prepareElements(this.svgElements);var t,e=this.options.iconWidth,i=15,s=4,o=s+.5*i;t="left"==this.options.orientation?s:this.width-e-s;for(var r in this.groups)this.groups.hasOwnProperty(r)&&(1!=this.groups[r].visible||void 0!==this.linegraphOptions.visibility[r]&&1!=this.linegraphOptions.visibility[r]||(this.groups[r].drawIcon(t,o,this.svgElements,this.svg,e,i),o+=i+s));n.cleanupElements(this.svgElements),this.iconsRemoved=!1},s.prototype._cleanupIcons=function(){0==this.iconsRemoved&&(n.prepareElements(this.svgElements),n.cleanupElements(this.svgElements),this.iconsRemoved=!0)},s.prototype.show=function(){this.hidden=!1,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.hidden=!0,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){0==this.master&&1==this.options.alignZeros&&-1!=this.zeroCrossing&&t>0&&(t=0),this.range.start=t,this.range.end=e},s.prototype.redraw=function(){var t=!1,e=0;this.dom.lineContainer.style.top=this.body.domProps.scrollTop+"px";for(var i in this.groups)this.groups.hasOwnProperty(i)&&(1!=this.groups[i].visible||void 0!==this.linegraphOptions.visibility[i]&&1!=this.linegraphOptions.visibility[i]||e++);if(0==this.amountOfGroups||0==e)this.hide();else{this.show(),this.height=Number(this.linegraphSVG.style.height.replace("px","")),this.dom.lineContainer.style.height=this.height+"px",this.width=1==this.options.visible?Number((""+this.options.width).replace("px","")):0;var s=this.props,o=this.dom.frame;o.className="dataaxis",this._calculateCharSize();var n=this.options.orientation,r=this.options.showMinorLabels,a=this.options.showMajorLabels;s.minorLabelHeight=r?s.minorCharHeight:0,s.majorLabelHeight=a?s.majorCharHeight:0,s.minorLineWidth=this.body.dom.backgroundHorizontal.offsetWidth-this.lineOffset-this.width+2*this.options.minorLinesOffset,s.minorLineHeight=1,s.majorLineWidth=this.body.dom.backgroundHorizontal.offsetWidth-this.lineOffset-this.width+2*this.options.majorLinesOffset,s.majorLineHeight=1,"left"==n?(o.style.top="0",o.style.left="0",o.style.bottom="",o.style.width=this.width+"px",o.style.height=this.height+"px",this.props.width=this.body.domProps.left.width,this.props.height=this.body.domProps.left.height):(o.style.top="",o.style.bottom="0",o.style.left="0",o.style.width=this.width+"px",o.style.height=this.height+"px",this.props.width=this.body.domProps.right.width,this.props.height=this.body.domProps.right.height),t=this._redrawLabels(),t=this._isResized()||t,1==this.options.icons?this._redrawGroupIcons():this._cleanupIcons(),this._redrawTitle(n)}return t},s.prototype._redrawLabels=function(){var t=!1;n.prepareElements(this.DOMelements.lines),n.prepareElements(this.DOMelements.labels);var e=this.options.orientation,i=this.master?this.props.majorCharHeight||10:this.stepPixelsForced,s=new a(this.range.start,this.range.end,i,this.dom.frame.offsetHeight,this.options.customRange[this.options.orientation],0==this.master&&this.options.alignZeros);this.step=s;var o=(this.dom.frame.offsetHeight-s.deadSpace*(this.dom.frame.offsetHeight/s.marginRange))/((s.marginRange-s.deadSpace)/s.step);this.stepPixels=o;var r=this.height/o,h=0;if(0==this.master){o=this.stepPixelsForced,h=Math.round(this.dom.frame.offsetHeight/o-r);for(var d=0;.5*h>d;d++)s.previous();if(r=this.height/o,-1!=this.zeroCrossing&&1==this.options.alignZeros){var l=s.marginEnd/s.step-this.zeroCrossing;if(l>0)for(var d=0;l>d;d++)s.next();else if(0>l)for(var d=0;-l>d;d++)s.previous()}}else r+=.25;this.valueAtZero=s.marginEnd;var c,p=0,u=1;void 0!==this.options.format[e]&&(c=this.options.format[e].decimals),this.maxLabelSize=0;for(var m=0;u=0&&this._redrawLabel(m-2,s.getCurrent(c),e,"yAxis major",this.props.majorCharHeight),this._redrawLine(m,e,"grid horizontal major",this.options.majorLinesOffset,this.props.majorLineWidth)):this._redrawLine(m,e,"grid horizontal minor",this.options.minorLinesOffset,this.props.minorLineWidth),1==this.master&&0==s.current&&(this.zeroCrossing=u),u++}this.conversionFactor=0==this.master?m/(this.valueAtZero-s.current):this.dom.frame.offsetHeight/s.marginRange;var g=0;void 0!==this.options.title[e]&&void 0!==this.options.title[e].text&&(g=this.props.titleCharHeight);var v=1==this.options.icons?Math.max(this.options.iconWidth,g)+this.options.labelOffsetX+15:g+this.options.labelOffsetX+15;return this.maxLabelSize>this.width-v&&1==this.options.visible?(this.width=this.maxLabelSize+v,this.options.width=this.width+"px",n.cleanupElements(this.DOMelements.lines),n.cleanupElements(this.DOMelements.labels),this.redraw(),t=!0):this.maxLabelSizethis.minWidth?(this.width=Math.max(this.minWidth,this.maxLabelSize+v),this.options.width=this.width+"px",n.cleanupElements(this.DOMelements.lines),n.cleanupElements(this.DOMelements.labels),this.redraw(),t=!0):(n.cleanupElements(this.DOMelements.lines),n.cleanupElements(this.DOMelements.labels),t=!1),t},s.prototype.convertValue=function(t){var e=this.valueAtZero-t,i=e*this.conversionFactor;return i},s.prototype._redrawLabel=function(t,e,i,s,o){var r=n.getDOMElement("div",this.DOMelements.labels,this.dom.frame);r.className=s,r.innerHTML=e,"left"==i?(r.style.left="-"+this.options.labelOffsetX+"px",r.style.textAlign="right"):(r.style.right="-"+this.options.labelOffsetX+"px",r.style.textAlign="left"),r.style.top=t-.5*o+this.options.labelOffsetY+"px",e+="";var a=Math.max(this.props.majorCharWidth,this.props.minorCharWidth);this.maxLabelSized;d++){var c=this.visibleItems[d];c.repositionY(e)}return s},s.prototype._calculateHeight=function(t){var e,i=this.visibleItems;this.resetSubgroups();var s=this;if(i.length){var n=i[0].top,r=i[0].top+i[0].height;if(o.forEach(i,function(t){n=Math.min(n,t.top),r=Math.max(r,t.top+t.height),void 0!==t.data.subgroup&&(s.subgroups[t.data.subgroup].height=Math.max(s.subgroups[t.data.subgroup].height,t.height),s.subgroups[t.data.subgroup].visible=!0)}),n>t.axis){var a=n-t.axis;r-=a,o.forEach(i,function(t){t.top-=a})}e=r+t.item.vertical/2}else e=t.axis+t.item.vertical;return e=Math.max(e,this.props.label.height)},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),void 0!==t.data.subgroup&&(void 0===this.subgroups[t.data.subgroup]&&(this.subgroups[t.data.subgroup]={height:0,visible:!1,index:this.subgroupIndex,items:[]},this.subgroupIndex++),this.subgroups[t.data.subgroup].items.push(t)),this.orderSubgroups(),-1==this.visibleItems.indexOf(t)){var e=this.itemSet.body.range;this._checkIfVisible(t,this.visibleItems,e)}},s.prototype.orderSubgroups=function(){if(void 0!==this.subgroupOrderer){var t=[];if("string"==typeof this.subgroupOrderer){for(var e in this.subgroups)t.push({subgroup:e,sortField:this.subgroups[e].items[0].data[this.subgroupOrderer]});t.sort(function(t,e){return t.sortField-e.sortField})}else if("function"==typeof this.subgroupOrderer){for(var e in this.subgroups)t.push(this.subgroups[e].items[0].data);t.sort(this.subgroupOrderer)}if(t.length>0)for(var i=0;it?-1:l>=t?0:1};if(e.length>0)for(n=0;nl}),1==this.checkRangedItems)for(this.checkRangedItems=!1,n=0;nl})}for(n=0;n=0&&(n=e[r],!o(n));r--)void 0===s[n.id]&&(s[n.id]=!0,i.push(n));for(r=t+1;rs;s++){var n=this.visibleItems[s];n.repositionY(e)}return i},s.prototype.show=function(){this.dom.background.parentNode||this.itemSet.dom.background.appendChild(this.dom.background)},t.exports=s},function(t,e,i){function s(t,e){this.body=t,this.defaultOptions={type:null,orientation:"bottom",align:"auto",stack:!0,groupOrder:null,selectable:!0,editable:{updateTime:!1,updateGroup:!1,add:!1,remove:!1},snap:h.snap,onAdd:function(t,e){e(t)},onUpdate:function(t,e){e(t)},onMove:function(t,e){e(t)},onRemove:function(t,e){e(t)},onMoving:function(t,e){e(t)},margin:{item:{horizontal:10,vertical:10},axis:20},padding:5},this.options=n.extend({},this.defaultOptions),this.itemOptions={type:{start:"Date",end:"Date"}},this.conversion={toScreen:t.util.toScreen,toTime:t.util.toTime},this.dom={},this.props={},this.hammer=null;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.groups={},this.groupIds=[],this.selection=[],this.stackDirty=!0,this.touchParams={},this._create(),this.setOptions(e)}var o=i(45),n=i(1),r=i(3),a=i(4),h=i(19),d=i(20),l=i(25),c=i(26),p=i(33),u=i(34),m=i(35),f=i(32),g="__ungrouped__",v="__background__";s.prototype=new d,s.types={background:f,box:p,range:m,point:u},s.prototype._create=function(){var t=document.createElement("div");t.className="itemset",t["timeline-itemset"]=this,this.dom.frame=t;var e=document.createElement("div");e.className="background",t.appendChild(e),this.dom.background=e;var i=document.createElement("div");i.className="foreground",t.appendChild(i),this.dom.foreground=i;var s=document.createElement("div");s.className="axis",this.dom.axis=s;var n=document.createElement("div");n.className="labelset",this.dom.labelSet=n,this._updateUngrouped();var r=new c(v,null,this);r.show(),this.groups[v]=r,this.hammer=o(this.body.dom.centerContainer,{preventDefault:!0}),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.hammer.on("tap",this._onSelectItem.bind(this)),this.hammer.on("hold",this._onMultiSelectItem.bind(this)),this.hammer.on("doubletap",this._onAddItem.bind(this)),this.show()},s.prototype.setOptions=function(t){if(t){var e=["type","align","orientation","padding","stack","selectable","groupOrder","dataAttributes","template","hide","snap"];n.selectiveExtend(e,this.options,t),"margin"in t&&("number"==typeof t.margin?(this.options.margin.axis=t.margin,this.options.margin.item.horizontal=t.margin,this.options.margin.item.vertical=t.margin):"object"==typeof t.margin&&(n.selectiveExtend(["axis"],this.options.margin,t.margin),"item"in t.margin&&("number"==typeof t.margin.item?(this.options.margin.item.horizontal=t.margin.item,this.options.margin.item.vertical=t.margin.item):"object"==typeof t.margin.item&&n.selectiveExtend(["horizontal","vertical"],this.options.margin.item,t.margin.item)))),"editable"in t&&("boolean"==typeof t.editable?(this.options.editable.updateTime=t.editable,this.options.editable.updateGroup=t.editable,this.options.editable.add=t.editable,this.options.editable.remove=t.editable):"object"==typeof t.editable&&n.selectiveExtend(["updateTime","updateGroup","add","remove"],this.options.editable,t.editable));var i=function(e){var i=t[e];if(i){if(!(i instanceof Function))throw new Error("option "+e+" must be a function "+e+"(item, callback)");this.options[e]=i}}.bind(this);["onAdd","onUpdate","onRemove","onMove","onMoving"].forEach(i),this.markDirty()}},s.prototype.markDirty=function(t){this.groupIds=[],this.stackDirty=!0,t&&t.refreshItems&&n.forEach(this.items,function(t){t.dirty=!0,t.displayed&&t.redraw()})},s.prototype.destroy=function(){this.hide(),this.setItems(null),this.setGroups(null),this.hammer=null,this.body=null,this.conversion=null},s.prototype.hide=function(){this.dom.frame.parentNode&&this.dom.frame.parentNode.removeChild(this.dom.frame),this.dom.axis.parentNode&&this.dom.axis.parentNode.removeChild(this.dom.axis),this.dom.labelSet.parentNode&&this.dom.labelSet.parentNode.removeChild(this.dom.labelSet)},s.prototype.show=function(){this.dom.frame.parentNode||this.body.dom.center.appendChild(this.dom.frame),this.dom.axis.parentNode||this.body.dom.backgroundVertical.appendChild(this.dom.axis),this.dom.labelSet.parentNode||this.body.dom.left.appendChild(this.dom.labelSet)},s.prototype.setSelection=function(t){var e,i,s,o;for(void 0==t&&(t=[]),Array.isArray(t)||(t=[t]),e=0,i=this.selection.length;i>e;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;this.props.top=this.body.domProps.top.height+this.body.domProps.border.top,this.props.left=this.body.domProps.left.width+this.body.domProps.border.left,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},f=0,g=t.axis+t.item.vertical;return this.groups[v].redraw(e,m,c),n.forEach(this.groups,function(t){var i=t==p?u:m,s=t.redraw(e,i,c);r=s||r,f+=t.height}),f=Math.max(f,g),this.stackDirty=!1,a.style.height=i(f),this.props.width=a.offsetWidth,this.props.height=f,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="0",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[g];return i||null},s.prototype._updateUngrouped=function(){{var t,e,i=this.groups[g];this.groups[v]}if(this.groupsData){if(i){i.hide(),delete this.groups[g];for(e in this.items)if(this.items.hasOwnProperty(e)){t=this.items[e],t.parent&&t.parent.remove(t);var s=this._getGroupId(t.data),o=this.groups[s];o&&o.add(t)||t.hide()}}}else if(!i){var n=null,r=null;i=new l(n,r,this),this.groups[g]=i;for(e in this.items)this.items.hasOwnProperty(e)&&(t=this.items[e],i.add(t));i.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",{queue:!0})},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._getType=function(t){return t.type||this.options.type||(t.end?"range":"box")},s.prototype._getGroupId=function(t){var e=this._getType(t);return"background"==e&&void 0==t.group?v:this.groupsData?t.group:g},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=e._getType(i),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",{queue:!0})},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",{queue:!0}))},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==g||t==v)throw new Error("Illegal group id. "+t+" is a reserved id.");var o=Object.create(e.options);n.extend(o,{height:null}),s=new l(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",{queue:!0})},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",{queue:!0})},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._getGroupId(t.data),i=this.groups[e];i&&i.add(t)},s.prototype._updateItem=function(t,e){var i=t.data.group;if(t.setData(e),i!=t.data.group){var s=this.groups[i];s&&s.remove(t);var o=this._getGroupId(t.data),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),t.parent&&t.parent.remove(t)},s.prototype._constructByEndArray=function(t){for(var e=[],i=0;i0||o.length>0)&&this.body.emitter.emit("select",{items:a})}},s.prototype._onAddItem=function(t){if(this.options.selectable&&this.options.editable.add){var e=this,i=this.options.snap||null,o=s.itemFromTarget(t);if(o){var r=e.itemsData.get(o.id);this.options.onUpdate(r,function(t){t&&e.itemsData.getDataSet().update(t)})}else{var a=n.getAbsoluteLeft(this.dom.frame),h=t.gesture.center.pageX-a,d=this.body.util.toTime(h),l=this.body.util.getScale(),c=this.body.util.getStep(),p={start:i?i(d,l,c):d,content:"new item"};if("range"===this.options.type){var u=this.body.util.toTime(h+this.props.width/5);p.end=i?i(u,l,c):u}p[this.itemsData._fieldId]=n.randomUUID();var m=this.groupFromTarget(t);m&&(p.group=m.groupId),this.options.onAdd(p,function(t){t&&e.itemsData.getDataSet().add(t)})}}},s.prototype._onMultiSelectItem=function(t){if(this.options.selectable){var e,i=s.itemFromTarget(t);if(i){e=this.getSelection();var o=t.gesture.touches[0]&&t.gesture.touches[0].shiftKey||!1;if(o){e.push(i.id);var n=s._getItemRange(this.itemsData.get(e,this.itemOptions));e=[];for(var r in this.items)if(this.items.hasOwnProperty(r)){var a=this.items[r],h=a.data.start,d=void 0!==a.data.end?a.data.end:h;h>=n.min&&d<=n.max&&e.push(a.id)}}else{var l=e.indexOf(i.id);-1==l?e.push(i.id):e.splice(l,1)}this.setSelection(e),this.body.emitter.emit("select",{items:this.getSelection()})}}},s._getItemRange=function(t){var e=null,i=null;return t.forEach(function(t){(null==i||t.starte)&&(e=t.end):(null==e||t.start>e)&&(e=t.start)}),{min:i,max:e}},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.prototype.groupFromTarget=function(t){for(var e=t.gesture.center.clientY,i=0;ia&&ea)return o}else if(0===i&&e"));this.dom.textArea.innerHTML=s,this.dom.textArea.style.lineHeight=.75*this.options.iconSize+this.options.iconSpacing+"px"}},s.prototype.drawLegendIcons=function(){if(this.dom.frame.parentNode){n.prepareElements(this.svgElements);var t=window.getComputedStyle(this.dom.frame).paddingTop,e=Number(t.replace("px","")),i=e,s=this.options.iconSize,o=.75*this.options.iconSize,r=e+.5*o+3;this.svg.style.width=s+5+e+"px";for(var a in this.groups)this.groups.hasOwnProperty(a)&&(1!=this.groups[a].visible||void 0!==this.linegraphOptions.visibility[a]&&1!=this.linegraphOptions.visibility[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,handleOverlap:"overlap",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,alignZeros:!0,customRange:{left:{min:void 0,max:void 0},right:{min:void 0,max:void 0}}},legend:{enabled:!1,icons:!0,left:{visible:!0,position:"top-left"},right:{visible:!0,position:"top-right"}},groups:{visibility:{}}},this.options=o.extend({},this.defaultOptions),this.dom={},this.props={},this.hammer=null,this.groups={},this.abortedGraphUpdate=!1,this.updateSVGheight=!1,this.updateSVGheightOnResize=!1;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.COUNTER=0,this.body.emitter.on("rangechanged",function(){i.lastStart=i.body.range.start,i.svg.style.left=o.option.asSize(-i.props.width),i.redraw.call(i,!0)}),this._create(),this.framework={svg:this.svg,svgElements:this.svgElements,options:this.options,groups:this.groups},this.body.emitter.emit("change")}var o=i(1),n=i(2),r=i(3),a=i(4),h=i(20),d=i(23),l=i(24),c=i(28),p=i(51),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.groups),this.options.dataAxis.orientation="right",this.yAxisRight=new d(this.body,this.options.dataAxis,this.svg,this.options.groups),delete this.options.dataAxis.orientation,this.legendLeft=new c(this.body,this.options.legend,"left",this.options.groups),this.legendRight=new c(this.body,this.options.legend,"right",this.options.groups),this.show()},s.prototype.setOptions=function(t){if(t){var e=["sampling","defaultGroup","height","graphHeight","yAxisOrientation","style","barChart","dataAxis","sort","groups"];void 0===t.graphHeight&&void 0!==t.height&&void 0!==this.body.domProps.centerContainer.height?(this.updateSVGheight=!0,this.updateSVGheightOnResize=!0):void 0!==this.body.domProps.centerContainer.height&&void 0!==t.graphHeight&&parseInt((t.graphHeight+"").replace("px",""))0){var d=this.body.util.toGlobalTime(-this.body.domProps.root.width),l=this.body.util.toGlobalTime(2*this.body.domProps.root.width),c={};for(this._getRelevantData(a,c,d,l),this._applySampling(a,c),e=0;eu&&console.log("WARNING: there may be an infinite loop in the _updateGraph emitter cycle."),this.COUNTER=0,this.abortedGraphUpdate=!1,e=0;e0)for(r=0;rs){d.push(h);break}d.push(h)}}else for(a=0;ai&&h.x0)for(var s=0;s0){var n=1,r=o.length,a=this.body.util.toGlobalScreen(o[o.length-1].x)-this.body.util.toGlobalScreen(o[0].x),h=r/a;n=Math.min(Math.ceil(.2*r),Math.max(1,Math.round(h)));for(var d=[],l=0;r>l;l+=n)d.push(o[l]);e[t[s]]=d}}},s.prototype._getYRanges=function(t,e,i){var s,o,n,r,a=[],h=[];if(t.length>0){for(n=0;n0&&(o=this.groups[t[n]],"stack"==r.barChart.handleOverlap&&"bar"==r.style?"left"==r.yAxisOrientation?a=a.concat(o.getYRange(s)):h=h.concat(o.getYRange(s)):i[t[n]]=o.getYRange(s,t[n]));p.getStackedBarYRange(a,i,t,"__barchartLeft","left"),p.getStackedBarYRange(h,i,t,"__barchartRight","right")}},s.prototype._updateYAxis=function(t,e){var i,s,o=!1,n=!1,r=!1,a=1e9,h=1e9,d=-1e9,l=-1e9;if(t.length>0){for(var c=0;ci?i:a,d=s>d?s:d):(r=!0,h=h>i?i:h,l=s>l?s:l));1==n&&this.yAxisLeft.setRange(a,d),1==r&&this.yAxisRight.setRange(h,l)}return o=this._toggleAxisVisiblity(n,this.yAxisLeft)||o,o=this._toggleAxisVisiblity(r,this.yAxisRight)||o,1==r&&1==n?(this.yAxisLeft.drawIcons=!0,this.yAxisRight.drawIcons=!0):(this.yAxisLeft.drawIcons=!1,this.yAxisRight.drawIcons=!1),this.yAxisRight.master=!n,0==this.yAxisRight.master?(this.yAxisLeft.lineOffset=1==r?this.yAxisRight.width:0,o=this.yAxisLeft.redraw()||o,this.yAxisRight.stepPixelsForced=this.yAxisLeft.stepPixels,this.yAxisRight.zeroCrossing=this.yAxisLeft.zeroCrossing,o=this.yAxisRight.redraw()||o):o=this.yAxisRight.redraw()||o,-1!=t.indexOf("__barchartLeft")&&t.splice(t.indexOf("__barchartLeft"),1),-1!=t.indexOf("__barchartRight")&&t.splice(t.indexOf("__barchartRight"),1),o},s.prototype._toggleAxisVisiblity=function(t,e){var i=!1;return 0==t?e.dom.frame.parentNode&&0==e.hidden&&(e.hide(),i=!0):e.dom.frame.parentNode||1!=e.hidden||(e.show(),i=!0),i},s.prototype._convertXcoordinates=function(t){for(var e,i,s=[],o=this.body.util.toScreen,n=0;ny;)y++,l=h.getCurrent(),c=h.isMajor(),u=h.getClassName(),f=m,m=this.body.util.toScreen(l),g=m-f,p&&(p.style.width=g+"px"),this.options.showMinorLabels&&this._repaintMinorText(m,h.getLabelMinor(),t,u),c&&this.options.showMajorLabels?(m>0&&(void 0==v&&(v=m),this._repaintMajorText(m,h.getLabelMajor(),t,u)),p=this._repaintMajorLine(m,t,u)):p=this._repaintMinorLine(m,t,u),h.next();if(this.options.showMajorLabels){var b=this.body.util.toTime(0),_=h.getLabelMajor(b),x=_.length*(this.props.majorCharWidth||10)+10;(void 0==v||v>x)&&this._repaintMajorText(0,_,t,u)}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,s){var o=this.dom.redundant.minorTexts.shift();if(!o){var n=document.createTextNode("");o=document.createElement("div"),o.appendChild(n),this.dom.foreground.appendChild(o)}this.dom.minorTexts.push(o),o.childNodes[0].nodeValue=e,o.style.top="top"==i?this.props.majorLabelHeight+"px":"0",o.style.left=t+"px",o.className="text minor "+s},s.prototype._repaintMajorText=function(t,e,i,s){var o=this.dom.redundant.majorTexts.shift();if(!o){var n=document.createTextNode(e);o=document.createElement("div"),o.appendChild(n),this.dom.foreground.appendChild(o)}this.dom.majorTexts.push(o),o.childNodes[0].nodeValue=e,o.className="text major "+s,o.style.top="top"==i?"0":this.props.minorLabelHeight+"px",o.style.left=t+"px"},s.prototype._repaintMinorLine=function(t,e,i){var s=this.dom.redundant.lines.shift();s||(s=document.createElement("div"),this.dom.background.appendChild(s)),this.dom.lines.push(s);var o=this.props;return s.style.top="top"==e?o.majorLabelHeight+"px":this.body.domProps.top.height+"px",s.style.height=o.minorLineHeight+"px",s.style.left=t-o.minorLineWidth/2+"px",s.className="grid vertical minor "+i,s},s.prototype._repaintMajorLine=function(t,e,i){var s=this.dom.redundant.lines.shift();s||(s=document.createElement("div"),this.dom.background.appendChild(s)),this.dom.lines.push(s);var o=this.props;return s.style.top="top"==e?"0":this.body.domProps.top.height+"px",s.style.left=t-o.majorLineWidth/2+"px",s.style.height=o.majorLineHeight+"px",s.className="grid vertical major "+i,s},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 major 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},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(45),n=i(1);s.prototype.stack=!0,s.prototype.select=function(){this.selected=!0,this.dirty=!0,this.displayed&&this.redraw()},s.prototype.unselect=function(){this.selected=!1,this.dirty=!0,this.displayed&&this.redraw()},s.prototype.setData=function(t){this.data=t,this.dirty=!0,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)},s.prototype._updateContents=function(t){var e;if(this.options.template){var i=this.parent.itemSet.itemsData.get(this.id);e=this.options.template(i)}else e=this.data.content;if(e!==this.content){if(e instanceof Element)t.innerHTML="",t.appendChild(e);else if(void 0!=e)t.innerHTML=e;else if("background"!=this.data.type||void 0!==this.data.content)throw new Error('Property "content" missing in item '+this.id);this.content=e}},s.prototype._updateTitle=function(t){null!=this.data.title?t.title=this.data.title||"":t.removeAttribute("title")},s.prototype._updateDataAttributes=function(t){if(this.options.dataAttributes&&this.options.dataAttributes.length>0){var e=[];if(Array.isArray(this.options.dataAttributes))e=this.options.dataAttributes;else{if("all"!=this.options.dataAttributes)return;e=Object.keys(this.data)}for(var i=0;it.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),this.dirty=!0),!this.parent)throw new Error("Cannot redraw item: no parent attached");if(!t.box.parentNode){var e=this.parent.dom.background;if(!e)throw new Error("Cannot redraw item: parent has no background container element");e.appendChild(t.box)}if(this.displayed=!0,this.dirty){this._updateContents(this.dom.content),this._updateTitle(this.dom.content),this._updateDataAttributes(this.dom.content),this._updateStyle(this.dom.box);var i=(this.data.className?" "+this.data.className:"")+(this.selected?" selected":"");t.box.className=this.baseClassName+i,this.overflow="hidden"!==window.getComputedStyle(t.content).overflow,this.props.content.width=this.dom.content.offsetWidth,this.height=0,this.dirty=!1}},s.prototype.show=r.prototype.show,s.prototype.hide=r.prototype.hide,s.prototype.repositionX=r.prototype.repositionX,s.prototype.repositionY=function(t){var e="top"===this.options.orientation;this.dom.content.style.top=e?"":"0",this.dom.content.style.bottom=e?"0":"";var i;if(void 0!==this.data.subgroup){var s=this.data.subgroup,o=this.parent.subgroups,r=o[s].index;if(1==e){i=this.parent.subgroups[s].height+t.item.vertical,i+=0==r?t.axis-.5*t.item.vertical:0;var a=this.parent.top;for(var h in o)o.hasOwnProperty(h)&&1==o[h].visible&&o[h].indexr&&(a+=o[h].height+t.item.vertical);i=this.parent.subgroups[s].height+t.item.vertical,this.dom.box.style.top=a+"px",this.dom.box.style.bottom=""}}else this.parent instanceof n?(i=Math.max(this.parent.height,this.parent.itemSet.body.domProps.center.height,this.parent.itemSet.body.domProps.centerContainer.height),this.dom.box.style.top=e?"0":"",this.dom.box.style.bottom=e?"":"0"):(i=this.parent.height,this.dom.box.style.top=this.parent.top+"px",this.dom.box.style.bottom="");this.dom.box.style.height=i+"px"},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(31);i(1)}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.dirty=!0),!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 item: parent has no foreground container element");e.appendChild(t.box)}if(this.displayed=!0,this.dirty){this._updateContents(this.dom.content),this._updateTitle(this.dom.box),this._updateDataAttributes(this.dom.box),this._updateStyle(this.dom.box);var i=(this.data.className?" "+this.data.className:"")+(this.selected?" selected":"");t.box.className=this.baseClassName+i,this.overflow="hidden"!==window.getComputedStyle(t.content).overflow,this.dom.content.style.maxWidth="none",this.props.content.width=this.dom.content.offsetWidth,this.height=this.dom.box.offsetHeight,this.dom.content.style.maxWidth="",this.dirty=!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,i=this.parent.width,s=this.conversion.toScreen(this.data.start),o=this.conversion.toScreen(this.data.end);-i>s&&(s=-i),o>2*i&&(o=2*i);var n=Math.max(o-s,1);switch(this.overflow?(this.left=s,this.width=n+this.props.content.width,e=this.props.content.width):(this.left=s,this.width=n,e=Math.min(o-s-2*this.options.padding,this.props.content.width)),this.dom.box.style.left=this.left+"px",this.dom.box.style.width=n+"px",this.options.align){case"left":this.dom.content.style.left="0";break;case"right":this.dom.content.style.left=Math.max(n-e-2*this.options.padding,0)+"px";break;case"center":this.dom.content.style.left=Math.max((n-e-2*this.options.padding)/2,0)+"px";break;default:t=this.overflow?o>0?Math.max(-s,0):-e:0>s?Math.min(-s,o-s-e-2*this.options.padding):0,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._determineBrowserMethod(),this._initializeMixinLoaders(),this.containerElement=t,this.renderRefreshRate=60,this.renderTimestep=1e3/this.renderRefreshRate,this.renderTime=0,this.physicsTime=0,this.runDoubleSpeed=!1,this.physicsDiscreteStepsize=.5,this.initializing=!0,this.triggerFunctions={add:null,edit:null,editEdge:null,connect:null,del:null};var o=function(t,e,i,s){if(e==t)return.5;var o=1/(e-t);return Math.max(0,(s-t)*o)};this.defaultOptions={nodes:{customScalingFunction:o,mass:1,radiusMin:10,radiusMax:30,radius:10,shape:"ellipse",image:void 0,widthMin:16,widthMax:64,fontColor:"black",fontSize:14,fontFace:"verdana",fontFill:void 0,fontStrokeWidth:0,fontStrokeColor:"#ffffff",fontDrawThreshold:3,scaleFontWithValue:!1,fontSizeMin:14,fontSizeMax:30,fontSizeMaxVisible:30,level:-1,color:{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"},hover:{border:"#2B7CE9",background:"#D2E5FF"}},group:void 0,borderWidth:1,borderWidthSelected:void 0},edges:{customScalingFunction:o,widthMin:1,widthMax:15,width:1,widthSelectionMultiplier:2,hoverWidth:1.5,style:"line",color:{color:"#848484",highlight:"#848484",hover:"#848484"},opacity:1,fontColor:"#343434",fontSize:14,fontFace:"arial",fontFill:"white",fontStrokeWidth:0,fontStrokeColor:"white",labelAlignment:"horizontal",arrowScaleFactor:1,dash:{length:10,gap:5,altLength:void 0},inheritColor:"from",useGradients:!1},configurePhysics:!1,physics:{barnesHut:{enabled:!0,thetaInverted:2,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,clusterByZoom:!0},navigation:{enabled:!1},keyboard:{enabled:!1,speed:{x:10,y:10,zoom:.02},bindToWindow:!0},dataManipulation:{enabled:!1,initiallyVisible:!1},hierarchicalLayout:{enabled:!1,levelSeparation:150,nodeSpacing:100,direction:"UD",layout:"hubsize"},freezeForStabilization:!1,smoothCurves:{enabled:!0,dynamic:!0,type:"continuous",roundness:.5},maxVelocity:50,minVelocity:.1,stabilize:!0,stabilizationIterations:1e3,zoomExtentOnStabilize:!0,locale:"en",locales:_,tooltip:{delay:300,fontColor:"black",fontSize:14,fontFace:"verdana",color:{border:"#666",background:"#FFFFC6"}},dragNetwork:!0,dragNodes:!0,zoomable:!0,hover:!1,hideEdgesOnDrag:!1,hideNodesOnDrag:!1,width:"100%",height:"100%",selectable:!0,useDefaultGroups:!0},this.constants=a.extend({},this.defaultOptions),this.pixelRatio=1,this.hoverObj={nodes:{},edges:{}},this.controlNodesActive=!1,this.navigationHammers={existing:[],_new:[]},this.animationSpeed=1/this.renderRefreshRate,this.animationEasingFunction="easeInOutQuint",this.animating=!1,this.easingTime=0,this.sourceScale=0,this.targetScale=0,this.sourceTranslation=0,this.targetTranslation=0,this.lockedOnNodeId=null,this.lockedOnNodeOffset=null,this.touchTime=0,this.redrawRequested=!1;var n=this;this.groups=new u,this.images=new m,this.images.setOnloadCallback(function(){n._requestRedraw()}),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.freezeSimulationEnabled=!1,this.cachedFunctions={},this.startedStabilization=!1,this.stabilized=!1,this.stabilizationIterations=null,this.draggingNodes=!1,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,e.data),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.constants.stabilize&&this.zoomExtent({duration:0},!0,this.constants.clustering.enabled),this.constants.clustering.enabled&&this.startWithClustering()}var o=i(56),n=i(45),r=i(58),a=i(1),h=i(47),d=i(3),l=i(4),c=i(42),p=i(43),u=i(38),m=i(39),f=i(40),g=i(37),v=i(41),y=i(54),b=i(55),_=i(49);i(50),o(s.prototype),s.prototype._determineBrowserMethod=function(){var t=navigator.userAgent.toLowerCase();this.requiresTimeout=!1,-1!=t.indexOf("msie 9.0")?this.requiresTimeout=!0:-1!=t.indexOf("safari")&&t.indexOf("chrome")<=-1&&(this.requiresTimeout=!0)},s.prototype._getScriptPath=function(){for(var t=document.getElementsByTagName("script"),e=0;e0)for(var r=0;re.boundingBox.left&&(o=e.boundingBox.left),ne.boundingBox.bottom&&(i=e.boundingBox.top),se.boundingBox.left&&(o=e.boundingBox.left),ne.boundingBox.bottom&&(i=e.boundingBox.top),s.5*this.nodeIndices.length)return void this.zoomExtent(t,!1,i); -s=this._getRange(t.nodes);var h=this.nodeIndices.length;o=1==this.constants.smoothCurves?1==this.constants.clustering.enabled&&h>=this.constants.clustering.initialMaxNodes?49.07548/(h+142.05338)+91444e-8:12.662/(h+7.4147)+.0964822:1==this.constants.clustering.enabled&&h>=this.constants.clustering.initialMaxNodes?77.5271985/(h+187.266146)+476710517e-13:30.5062972/(h+19.93597763)+.08413486;var d=Math.min(this.frame.canvas.clientWidth/600,this.frame.canvas.clientHeight/600);o*=d}else{s=this._getRange(t.nodes);var l=1.1*Math.abs(s.maxX-s.minX),c=1.1*Math.abs(s.maxY-s.minY),p=this.frame.canvas.clientWidth/l,u=this.frame.canvas.clientHeight/c;o=u>=p?p:u}o>1&&(o=1);var m=this._findCenter(s);if(0==i){var t={position:m,scale:o,animation:t};this.moveTo(t),this.moving=!0,this.start()}else m.x*=o,m.y*=o,m.x-=.5*this.frame.canvas.clientWidth,m.y-=.5*this.frame.canvas.clientHeight,this._setScale(o),this._setTranslation(-m.x,-m.y)},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),this._unselectAll(!0),this.initializing=!0,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(1==this.constants.dataManipulation.enabled&&this._createManipulatorBar(),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);this._putDataInSector(),0==e&&(1==this.constants.hierarchicalLayout.enabled?(this._resetLevels(),this._setupHierarchicalLayout()):1==this.constants.stabilize&&this._stabilize(),this.start()),this.initializing=!1},s.prototype.setOptions=function(t){if(t){var e,i=["nodes","edges","smoothCurves","hierarchicalLayout","clustering","navigation","keyboard","dataManipulation","onAdd","onEdit","onEditEdge","onConnect","onDelete","clickToUse"];if(a.selectiveNotDeepExtend(i,this.constants,t),a.selectiveNotDeepExtend(["color"],this.constants.nodes,t.nodes),a.selectiveNotDeepExtend(["color","length"],this.constants.edges,t.edges),this.groups.useDefaultGroups=this.constants.useDefaultGroups,t.physics&&(a.mergeOptions(this.constants.physics,t.physics,"barnesHut"),a.mergeOptions(this.constants.physics,t.physics,"repulsion"),t.physics.hierarchicalRepulsion)){this.constants.hierarchicalLayout.enabled=!0,this.constants.physics.hierarchicalRepulsion.enabled=!0,this.constants.physics.barnesHut.enabled=!1;for(e in t.physics.hierarchicalRepulsion)t.physics.hierarchicalRepulsion.hasOwnProperty(e)&&(this.constants.physics.hierarchicalRepulsion[e]=t.physics.hierarchicalRepulsion[e])}if(t.onAdd&&(this.triggerFunctions.add=t.onAdd),t.onEdit&&(this.triggerFunctions.edit=t.onEdit),t.onEditEdge&&(this.triggerFunctions.editEdge=t.onEditEdge),t.onConnect&&(this.triggerFunctions.connect=t.onConnect),t.onDelete&&(this.triggerFunctions.del=t.onDelete),a.mergeOptions(this.constants,t,"smoothCurves"),a.mergeOptions(this.constants,t,"hierarchicalLayout"),a.mergeOptions(this.constants,t,"clustering"),a.mergeOptions(this.constants,t,"navigation"),a.mergeOptions(this.constants,t,"keyboard"),a.mergeOptions(this.constants,t,"dataManipulation"),t.dataManipulation&&(this.editMode=this.constants.dataManipulation.initiallyVisible),t.edges&&(void 0!==t.edges.color&&(a.isString(t.edges.color)?(this.constants.edges.color={},this.constants.edges.color.color=t.edges.color,this.constants.edges.color.highlight=t.edges.color,this.constants.edges.color.hover=t.edges.color):(void 0!==t.edges.color.color&&(this.constants.edges.color.color=t.edges.color.color),void 0!==t.edges.color.highlight&&(this.constants.edges.color.highlight=t.edges.color.highlight),void 0!==t.edges.color.hover&&(this.constants.edges.color.hover=t.edges.color.hover)),this.constants.edges.inheritColor=!1),t.edges.fontColor||void 0!==t.edges.color&&(a.isString(t.edges.color)?this.constants.edges.fontColor=t.edges.color:void 0!==t.edges.color.color&&(this.constants.edges.fontColor=t.edges.color.color))),t.nodes&&t.nodes.color){var s=a.parseColor(t.nodes.color);this.constants.nodes.color.background=s.background,this.constants.nodes.color.border=s.border,this.constants.nodes.color.highlight.background=s.highlight.background,this.constants.nodes.color.highlight.border=s.highlight.border,this.constants.nodes.color.hover.background=s.hover.background,this.constants.nodes.color.hover.border=s.hover.border}if(t.groups)for(var o in t.groups)if(t.groups.hasOwnProperty(o)){var n=t.groups[o];this.groups.add(o,n)}if(t.tooltip){for(e in t.tooltip)t.tooltip.hasOwnProperty(e)&&(this.constants.tooltip[e]=t.tooltip[e]);t.tooltip.color&&(this.constants.tooltip.color=a.parseColor(t.tooltip.color))}if("clickToUse"in t&&(t.clickToUse?this.activator||(this.activator=new b(this.frame),this.activator.on("change",this._createKeyBinds.bind(this))):this.activator&&(this.activator.destroy(),delete this.activator)),t.labels)throw new Error('Option "labels" is deprecated. Use options "locale" and "locales" instead.');this._loadPhysicsSystem(),this._loadNavigationControls(),this._loadManipulationSystem(),this._configureSmoothCurves(),this._bindHammer(),this._createKeyBinds(),this._markAllEdgesAsDirty(),this.setSize(this.constants.width,this.constants.height),this.moving=!0,1==this.constants.hierarchicalLayout.enabled&&0==this.initializing&&(this._resetLevels(),this._setupHierarchicalLayout()),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="vis network-frame",this.frame.style.position="relative",this.frame.style.overflow="hidden",this.frame.tabIndex=900,this.frame.canvas=document.createElement("canvas"),this.frame.canvas.style.position="relative",this.frame.appendChild(this.frame.canvas),this.frame.canvas.getContext){var t=this.frame.canvas.getContext("2d");this.pixelRatio=(window.devicePixelRatio||1)/(t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1),this.frame.canvas.getContext("2d").setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0)}else{var e=document.createElement("DIV");e.style.color="red",e.style.fontWeight="bold",e.style.padding="10px",e.innerHTML="Error: your browser does not support HTML canvas",this.frame.canvas.appendChild(e)}this._bindHammer()},s.prototype._bindHammer=function(){var t=this;void 0!==this.hammer&&this.hammer.dispose(),this.drag={},this.pinch={},this.hammer=n(this.frame.canvas,{prevent_default:!0}),this.hammer.on("tap",t._onTap.bind(t)),this.hammer.on("doubletap",t._onDoubleTap.bind(t)),this.hammer.on("hold",t._onHold.bind(t)),this.hammer.on("touch",t._onTouch.bind(t)),this.hammer.on("dragstart",t._onDragStart.bind(t)),this.hammer.on("drag",t._onDrag.bind(t)),this.hammer.on("dragend",t._onDragEnd.bind(t)),1==this.constants.zoomable&&(this.hammer.on("mousewheel",t._onMouseWheel.bind(t)),this.hammer.on("DOMMouseScroll",t._onMouseWheel.bind(t)),this.hammer.on("pinch",t._onPinch.bind(t))),this.hammer.on("mousemove",t._onMouseMoveTitle.bind(t)),this.hammerFrame=n(this.frame,{prevent_default:!0}),this.hammerFrame.on("release",t._onRelease.bind(t)),this.containerElement.appendChild(this.frame)},s.prototype._createKeyBinds=function(){var t=this;void 0!==this.keycharm&&this.keycharm.destroy(),this.keycharm=r(1==this.constants.keyboard.bindToWindow?{container:window,preventDefault:!1}:{container:this.frame,preventDefault:!1}),this.keycharm.reset(),this.constants.keyboard.enabled&&this.isActive()&&(this.keycharm.bind("up",this._moveUp.bind(t),"keydown"),this.keycharm.bind("up",this._yStopMoving.bind(t),"keyup"),this.keycharm.bind("down",this._moveDown.bind(t),"keydown"),this.keycharm.bind("down",this._yStopMoving.bind(t),"keyup"),this.keycharm.bind("left",this._moveLeft.bind(t),"keydown"),this.keycharm.bind("left",this._xStopMoving.bind(t),"keyup"),this.keycharm.bind("right",this._moveRight.bind(t),"keydown"),this.keycharm.bind("right",this._xStopMoving.bind(t),"keyup"),this.keycharm.bind("=",this._zoomIn.bind(t),"keydown"),this.keycharm.bind("=",this._stopZoom.bind(t),"keyup"),this.keycharm.bind("num+",this._zoomIn.bind(t),"keydown"),this.keycharm.bind("num+",this._stopZoom.bind(t),"keyup"),this.keycharm.bind("num-",this._zoomOut.bind(t),"keydown"),this.keycharm.bind("num-",this._stopZoom.bind(t),"keyup"),this.keycharm.bind("-",this._zoomOut.bind(t),"keydown"),this.keycharm.bind("-",this._stopZoom.bind(t),"keyup"),this.keycharm.bind("[",this._zoomIn.bind(t),"keydown"),this.keycharm.bind("[",this._stopZoom.bind(t),"keyup"),this.keycharm.bind("]",this._zoomOut.bind(t),"keydown"),this.keycharm.bind("]",this._stopZoom.bind(t),"keyup"),this.keycharm.bind("pageup",this._zoomIn.bind(t),"keydown"),this.keycharm.bind("pageup",this._stopZoom.bind(t),"keyup"),this.keycharm.bind("pagedown",this._zoomOut.bind(t),"keydown"),this.keycharm.bind("pagedown",this._stopZoom.bind(t),"keyup")),1==this.constants.dataManipulation.enabled&&(this.keycharm.bind("esc",this._createManipulatorBar.bind(t)),this.keycharm.bind("delete",this._deleteSelected.bind(t)))},s.prototype.destroy=function(){this.start=function(){},this.redraw=function(){},this.timer=!1,this._cleanupPhysicsConfiguration(),this.keycharm.reset(),this.hammer.dispose(),this.off(),this._recursiveDOMDelete(this.containerElement)},s.prototype._recursiveDOMDelete=function(t){for(;1==t.hasChildNodes();)this._recursiveDOMDelete(t.firstChild),t.removeChild(t.firstChild)},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){(new Date).valueOf()-this.touchTime>100&&(this.drag.pointer=this._getPointer(t.gesture.center),this.drag.pinched=!1,this.pinch.scale=this._getScale(),this.touchTime=(new Date).valueOf(),this._handleTouch(this.drag.pointer))},s.prototype._onDragStart=function(t){this._handleDragStart(t)},s.prototype._handleDragStart=function(t){void 0===this.drag.pointer&&this._onTouch(t);var e=this._getNodeAt(this.drag.pointer);if(this.drag.dragging=!0,this.drag.selection=[],this.drag.translation=this._getTranslation(),this.drag.nodeId=null,this.draggingNodes=!1,null!=e&&1==this.constants.dragNodes){this.draggingNodes=!0,this.drag.nodeId=e.id,e.isSelected()||this._selectObject(e,!1),this.emit("dragStart",{nodeIds:this.getSelection().nodes});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,this.drag.selection.push(o)}}},s.prototype._onDrag=function(t){this._handleOnDrag(t)},s.prototype._handleOnDrag=function(t){if(!this.drag.pinched){this.releaseNode();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){if(void 0===this.drag.pointer)return void this._handleDragStart(t);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(t){this._handleDragEnd(t)},s.prototype._handleDragEnd=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(),0==this.draggingNodes?this.emit("dragEnd",{nodeIds:[]}):this.emit("dragEnd",{nodeIds:this.getSelection().nodes})},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),s=!1;if(void 0!==this.popup&&(this.popup.hidden===!1&&this._checkHidePopup(i),this.popup.hidden===!1&&(s=!0,this.popup.setPosition(i.x+3,i.y-5),this.popup.show())),0==this.constants.keyboard.bindToWindow&&1==this.constants.keyboard.enabled&&this.frame.focus(),s===!1){var o=this,n=function(){o._checkShowPopup(i)};this.popupTimer&&clearInterval(this.popupTimer),this.drag.dragging||(this.popupTimer=setTimeout(n,this.constants.tooltip.delay))}if(1==this.constants.hover){for(var r in this.hoverObj.edges)this.hoverObj.edges.hasOwnProperty(r)&&(this.hoverObj.edges[r].hover=!1,delete this.hoverObj.edges[r]);var a=this._getNodeAt(i);null==a&&(a=this._getEdgeAt(i)),null!=a&&this._hoverObject(a);for(var d in this.hoverObj.nodes)this.hoverObj.nodes.hasOwnProperty(d)&&(a instanceof f&&a.id!=d||a instanceof g||null==a)&&(this._blurObject(this.hoverObj.nodes[d]),delete this.hoverObj.nodes[d]);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=void 0===this.popupObj?"":this.popupObj.id,o=!1,n="node";if(void 0==this.popupObj){var r=this.nodes,a=[];for(e in r)if(r.hasOwnProperty(e)){var h=r[e];h.isOverlappingWith(i)&&void 0!==h.getTitle()&&a.push(e)}a.length>0&&(this.popupObj=this.nodes[a[a.length-1]],o=!0)}if(void 0===this.popupObj&&0==o){var d=this.edges,l=[];for(e in d)if(d.hasOwnProperty(e)){var c=d[e];c.connected&&void 0!==c.getTitle()&&c.isOverlappingWith(i)&&l.push(e)}l.length>0&&(this.popupObj=this.edges[l[l.length-1]],n="edge")}this.popupObj?this.popupObj.id!=s&&(void 0===this.popup&&(this.popup=new v(this.frame,this.constants.tooltip)),this.popup.popupTargetType=n,this.popup.popupTargetId=this.popupObj.id,this.popup.setPosition(t.x+3,t.y-5),this.popup.setText(this.popupObj.getTitle()),this.popup.show()):this.popup&&this.popup.hide()},s.prototype._checkHidePopup=function(t){var e={left:this._XconvertDOMtoCanvas(t.x),top:this._YconvertDOMtoCanvas(t.y),right:this._XconvertDOMtoCanvas(t.x),bottom:this._YconvertDOMtoCanvas(t.y)},i=!1;if("node"==this.popup.popupTargetType){if(i=this.nodes[this.popup.popupTargetId].isOverlappingWith(e),i===!0){var s=this._getNodeAt(t);i=s.id==this.popup.popupTargetId}}else null===this._getNodeAt(t)&&(i=this.edges[this.popup.popupTargetId].isOverlappingWith(e));i===!1&&(this.popupObj=void 0,this.popup.hide())},s.prototype.setSize=function(t,e){var i=!1,s=this.frame.canvas.width,o=this.frame.canvas.height;t!=this.constants.width||e!=this.constants.height||this.frame.style.width!=t||this.frame.style.height!=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.pixelRatio,this.frame.canvas.height=this.frame.canvas.clientHeight*this.pixelRatio,this.constants.width=t,this.constants.height=e,i=!0):(this.frame.canvas.width!=this.frame.canvas.clientWidth*this.pixelRatio&&(this.frame.canvas.width=this.frame.canvas.clientWidth*this.pixelRatio,i=!0),this.frame.canvas.height!=this.frame.canvas.clientHeight*this.pixelRatio&&(this.frame.canvas.height=this.frame.canvas.clientHeight*this.pixelRatio,i=!0)),1==i&&this.emit("resize",{width:this.frame.canvas.width*this.pixelRatio,height:this.frame.canvas.height*this.pixelRatio,oldWidth:s*this.pixelRatio,oldHeight:o*this.pixelRatio})},s.prototype._setNodes=function(t){var e=this.nodesData;if(t instanceof d||t instanceof l)this.nodesData=t;else if(Array.isArray(t))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 f(o,this.images,this.groups,this.constants);if(this.nodes[e]=n,!(0!=n.xFixed&&0!=n.yFixed||null!==n.x&&null!==n.y)){var r=1*t.length+10,a=2*Math.PI*Math.random();0==n.xFixed&&(n.x=r*Math.cos(a)),0==n.yFixed&&(n.y=r*Math.sin(a))}this.moving=!0}this._updateNodeIndexList(),1==this.constants.hierarchicalLayout.enabled&&0==this.initializing&&(this._resetLevels(),this._setupHierarchicalLayout()),this._updateCalculationNodes(),this._reconnectEdges(),this._updateValueRange(this.nodes),this.updateLabels()},s.prototype._updateNodes=function(t,e){for(var i=this.nodes,s=0,o=t.length;o>s;s++){var n=t[s],r=i[n],a=e[s];r?r.setProperties(a,this.constants):(r=new f(properties,this.images,this.groups,this.constants),i[n]=r)}this.moving=!0,1==this.constants.hierarchicalLayout.enabled&&0==this.initializing&&(this._resetLevels(),this._setupHierarchicalLayout()),this._updateNodeIndexList(),this._updateValueRange(i),this._markAllEdgesAsDirty()},s.prototype._markAllEdgesAsDirty=function(){for(var t in this.edges)this.edges[t].colorDirty=!0},s.prototype._removeNodes=function(t){for(var e=this.nodes,i=0,s=t.length;s>i;i++)void 0!==this.selectionObj.nodes[t[i]]&&(this.nodes[t[i]].unselect(),this._removeFromSelection(this.nodes[t[i]]));for(var 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(Array.isArray(t))this.edgesData=new d,this.edgesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.edgesData=new d}if(e&&a.forEach(this.edgesListeners,function(t,i){e.off(i,t)}),this.edges={},this.edgesData){var i=this;a.forEach(this.edgesListeners,function(t,e){i.edgesData.on(e,t)});var s=this.edgesData.getIds();this._addEdges(s)}this._reconnectEdges()},s.prototype._addEdges=function(t){for(var e=this.edges,i=this.edgesData,s=0,o=t.length;o>s;s++){var n=t[s],r=e[n];r&&r.disconnect();var a=i.get(n,{showInternalIds:!0});e[n]=new g(a,this,this.constants)}this.moving=!0,this._updateValueRange(e),this._createBezierNodes(),this._updateCalculationNodes(),1==this.constants.hierarchicalLayout.enabled&&0==this.initializing&&(this._resetLevels(),this._setupHierarchicalLayout())},s.prototype._updateEdges=function(t){for(var e=this.edges,i=this.edgesData,s=0,o=t.length;o>s;s++){var n=t[s],r=i.get(n),a=e[n];a?(a.disconnect(),a.setProperties(r,this.constants),a.connect()):(a=new g(r,this,this.constants),this.edges[n]=a)}this._createBezierNodes(),1==this.constants.hierarchicalLayout.enabled&&0==this.initializing&&(this._resetLevels(),this._setupHierarchicalLayout()),this.moving=!0,this._updateValueRange(e)},s.prototype._removeEdges=function(t){for(var e=this.edges,i=0,s=t.length;s>i;i++)void 0!==this.selectionObj.edges[t[i]]&&(e[t[i]].unselect(),this._removeFromSelection(e[t[i]]));for(var 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=[],e[t].dynamicEdges=[]);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,o=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),o+=n)}if(void 0!==i&&void 0!==s)for(e in t)t.hasOwnProperty(e)&&t[e].setValueRange(i,s,o)},s.prototype.redraw=function(){this.setSize(this.constants.width,this.constants.height),this._redraw()},s.prototype._requestRedraw=function(t){this.redrawRequested!==!0&&(this.redrawRequested=!0,this.requiresTimeout===!0?window.setTimeout(this._redraw.bind(this,t),0):window.requestAnimationFrame(this._redraw.bind(this,t,!0)))},s.prototype._redraw=function(t){void 0===t&&(t=!1),this.redrawRequested=!1;var e=this.frame.canvas.getContext("2d");e.setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0);var i=this.frame.canvas.clientWidth,s=this.frame.canvas.clientHeight;e.clearRect(0,0,i,s),e.save(),e.translate(this.translation.x,this.translation.y),e.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)},t===!1&&(this._doInAllSectors("_drawAllSectorNodes",e),(0==this.drag.dragging||void 0===this.drag.dragging||0==this.constants.hideEdgesOnDrag)&&this._doInAllSectors("_drawEdges",e)),(0==this.drag.dragging||void 0===this.drag.dragging||0==this.constants.hideNodesOnDrag)&&this._doInAllSectors("_drawNodes",e,!1),t===!1&&1==this.controlNodesActive&&this._doInAllSectors("_drawControlNodes",e),e.restore(),t===!0&&e.clearRect(0,0,i,s)},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);return o>.5*this.constants.maxVelocity?!0:this._isMoving(o)}return!1},s.prototype._revertPhysicsState=function(){var t=this.nodes;for(var e in t)t.hasOwnProperty(e)&&t[e].revertPosition()},s.prototype._revertPhysicsTick=function(){this._doInAllActiveSectors("_revertPhysicsState"),1==this.constants.smoothCurves.enabled&&1==this.constants.smoothCurves.dynamic&&this._doInSupportSector("_revertPhysicsState")},s.prototype._physicsTick=function(){if(!this.freezeSimulationEnabled&&1==this.moving){var t=!1,e=!1;this._doInAllActiveSectors("_initializeForceCalculation");var i=this._doInAllActiveSectors("_discreteStepNodes");1==this.constants.smoothCurves.enabled&&1==this.constants.smoothCurves.dynamic&&(e=this._doInSupportSector("_discreteStepNodes"));for(var s=0;s2*e||1==this.runDoubleSpeed)&&1==this.moving&&(this._physicsTick(),0!=this.renderTime&&(this.runDoubleSpeed=!0))}var i=Date.now();this._redraw(),this.renderTime=Date.now()-i,0==this.requiresTimeout&&this.start()},"undefined"!=typeof window&&(window.requestAnimationFrame=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame),s.prototype.start=function(){if(1==this.freezeSimulationEnabled&&(this.moving=!1),1==this.moving||0!=this.xIncrement||0!=this.yIncrement||0!=this.zoomIncrement||1==this.animating)this.timer||(this.timer=1==this.requiresTimeout?window.setTimeout(this._animationStep.bind(this),this.renderTimestep):window.requestAnimationFrame(this._animationStep.bind(this)));else if(this._requestRedraw(),this.stabilizationIterations>1){var t=this,e={iterations:t.stabilizationIterations};this.stabilizationIterations=0,this.startedStabilization=!1,setTimeout(function(){t.emit("stabilized",e)},0)}else this.stabilizationIterations=0},s.prototype._handleNavigation=function(){if(0!=this.xIncrement||0!=this.yIncrement){var t=this._getTranslation();this._setTranslation(t.x+this.xIncrement,t.y+this.yIncrement)}if(0!=this.zoomIncrement){var e={x:this.frame.canvas.clientWidth/2,y:this.frame.canvas.clientHeight/2};this._zoom(this.scale*(1+this.zoomIncrement),e)}},s.prototype.freezeSimulation=function(t){1==t?(this.freezeSimulationEnabled=!0,this.moving=!1):(this.freezeSimulationEnabled=!1,this.moving=!0,this.start())},s.prototype._configureSmoothCurves=function(t){if(void 0===t&&(t=!0),1==this.constants.smoothCurves.enabled&&1==this.constants.smoothCurves.dynamic){this._createBezierNodes();for(var e in this.sectors.support.nodes)this.sectors.support.nodes.hasOwnProperty(e)&&void 0===this.edges[this.sectors.support.nodes[e].parentEdgeId]&&delete this.sectors.support.nodes[e]}else{this.sectors.support.nodes={};for(var i in this.edges)this.edges.hasOwnProperty(i)&&(this.edges[i].via=null)}this._updateCalculationNodes(),t||(this.moving=!0,this.start())},s.prototype._createBezierNodes=function(){if(1==this.constants.smoothCurves.enabled&&1==this.constants.smoothCurves.dynamic)for(var t in this.edges)if(this.edges.hasOwnProperty(t)){var e=this.edges[t];if(null==e.via){var i="edgeId:".concat(e.id);this.sectors.support.nodes[i]=new f({id:i,mass:1,shape:"circle",image:"",internalMultiplier:1},{},{},this.constants),e.via=this.sectors.support.nodes[i],e.via.parentEdgeId=e.id,e.positionBezierNode()}}},s.prototype._initializeMixinLoaders=function(){for(var t in y)y.hasOwnProperty(t)&&(s.prototype[t]=y[t])},s.prototype.storePosition=function(){console.log("storePosition is depricated: use .storePositions() from now on."),this.storePositions()},s.prototype.storePositions=function(){var t=[];for(var e in this.nodes)if(this.nodes.hasOwnProperty(e)){var i=this.nodes[e],s=!this.nodes.xFixed,o=!this.nodes.yFixed;(this.nodesData._data[e].x!=Math.round(i.x)||this.nodesData._data[e].y!=Math.round(i.y))&&t.push({id:e,x:Math.round(i.x),y:Math.round(i.y),allowedToMoveX:s,allowedToMoveY:o})}this.nodesData.update(t)},s.prototype.getPositions=function(t){var e={};if(void 0!==t){if(1==Array.isArray(t)){for(var i=0;i=1&&(this.animating=!1,this.easingTime=0,this._redraw=null!=this.lockedOnNodeId?this._lockedRedraw:this._classicRedraw,this.emit("animationFinished"))},s.prototype._classicRedraw=function(){},s.prototype.isActive=function(){return!this.activator||this.activator.active},s.prototype.setScale=function(){return this._setScale()},s.prototype.getScale=function(){return this._getScale()},s.prototype.getCenterCoordinates=function(){return this.DOMtoCanvas({x:.5*this.frame.canvas.clientWidth,y:.5*this.frame.canvas.clientHeight})},s.prototype.getBoundingBox=function(t){return void 0!==this.nodes[t]?this.nodes[t].boundingBox:void 0},s.prototype.getConnectedNodes=function(t){var e=[];if(void 0!==this.nodes[t])for(var i=this.nodes[t],s={nodeId:!0},o=0;oh}return!1},s.prototype._getColor=function(t){var e=this.options.color;if(1==this.options.useGradients){var i,s,n=t.createLinearGradient(this.from.x,this.from.y,this.to.x,this.to.y);return i=this.from.options.color.highlight.border,s=this.to.options.color.highlight.border,0==this.from.selected&&0==this.to.selected?(i=o.overrideOpacity(this.from.options.color.border,this.options.opacity),s=o.overrideOpacity(this.to.options.color.border,this.options.opacity)):1==this.from.selected&&0==this.to.selected?s=this.to.options.color.border:0==this.from.selected&&1==this.to.selected&&(i=this.from.options.color.border),n.addColorStop(0,i),n.addColorStop(1,s),n}return this.colorDirty===!0&&("to"==this.options.inheritColor?e={highlight:this.to.options.color.highlight.border,hover:this.to.options.color.hover.border,color:o.overrideOpacity(this.from.options.color.border,this.options.opacity)}:("from"==this.options.inheritColor||1==this.options.inheritColor)&&(e={highlight:this.from.options.color.highlight.border,hover:this.from.options.color.hover.border,color:o.overrideOpacity(this.from.options.color.border,this.options.opacity)}),this.options.color=e,this.colorDirty=!1),1==this.selected?e.highlight:1==this.hover?e.hover:e.color},s.prototype._drawLine=function(t){if(t.strokeStyle=this._getColor(t),t.lineWidth=this._getLineWidth(),this.from!=this.to){var e,i=this._line(t);if(this.label){if(1==this.options.smoothCurves.enabled&&null!=i){var s=.5*(.5*(this.from.x+i.x)+.5*(this.to.x+i.x)),o=.5*(.5*(this.from.y+i.y)+.5*(this.to.y+i.y));e={x:s,y:o}}else e=this._pointOnLine(.5);this._label(t,this.label,e.x,e.y)}}else{var n,r,a=this.physics.springLength/4,h=this.from;h.width||h.resize(t),h.width>h.height?(n=h.x+h.width/2,r=h.y-a):(n=h.x+a,r=h.y-h.height/2),this._circle(t,n,r,a),e=this._pointOnCircle(n,r,a,.5),this._label(t,this.label,e.x,e.y)}},s.prototype._getLineWidth=function(){return 1==this.selected?Math.max(Math.min(this.widthSelected,this.options.widthMax),.3*this.networkScaleInv):1==this.hover?Math.max(Math.min(this.options.hoverWidth,this.options.widthMax),.3*this.networkScaleInv):Math.max(this.options.width,.3*this.networkScaleInv)},s.prototype._getViaCoordinates=function(){if(1==this.options.smoothCurves.dynamic&&1==this.options.smoothCurves.enabled)return this.via;if(0==this.options.smoothCurves.enabled)return{x:0,y:0};var t=null,e=null,i=this.options.smoothCurves.roundness,s=this.options.smoothCurves.type,o=Math.abs(this.from.x-this.to.x),n=Math.abs(this.from.y-this.to.y);if("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));else if("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.yd;d++){var l=t.measureText(n[d]).width;h=l>h?l:h}var c=this.options.fontSize*r,p=i-h/2,u=s-c/2;this.labelDimensions={top:u,left:p,width:h,height:c,yLine:o}}var o=this.labelDimensions.yLine;t.save(),"horizontal"!=this.options.labelAlignment&&(t.translate(i,o),this._rotateForLabelAlignment(t),i=0,o=0),this._drawLabelRect(t),this._drawLabelText(t,i,o,n,r,a),t.restore()}},s.prototype._rotateForLabelAlignment=function(t){var e=this.from.y-this.to.y,i=this.from.x-this.to.x,s=Math.atan2(e,i);(-1>s&&0>i||s>0&&0>i)&&(s+=Math.PI),t.rotate(s)},s.prototype._drawLabelRect=function(t){if(void 0!==this.options.fontFill&&null!==this.options.fontFill&&"none"!==this.options.fontFill){t.fillStyle=this.options.fontFill;var e=2;"line-center"==this.options.labelAlignment?t.fillRect(.5*-this.labelDimensions.width,.5*-this.labelDimensions.height,this.labelDimensions.width,this.labelDimensions.height):"line-above"==this.options.labelAlignment?t.fillRect(.5*-this.labelDimensions.width,-(this.labelDimensions.height+e),this.labelDimensions.width,this.labelDimensions.height):"line-below"==this.options.labelAlignment?t.fillRect(.5*-this.labelDimensions.width,e,this.labelDimensions.width,this.labelDimensions.height):t.fillRect(this.labelDimensions.left,this.labelDimensions.top,this.labelDimensions.width,this.labelDimensions.height)}},s.prototype._drawLabelText=function(t,e,i,s,o,n){if(t.fillStyle=this.options.fontColor||"black",t.textAlign="center","horizontal"!=this.options.labelAlignment){var r=2;"line-above"==this.options.labelAlignment?(t.textBaseline="alphabetic",i-=2*r):"line-below"==this.options.labelAlignment?(t.textBaseline="hanging",i+=2*r):t.textBaseline="middle"}else t.textBaseline="middle";this.options.fontStrokeWidth>0&&(t.lineWidth=this.options.fontStrokeWidth,t.strokeStyle=this.options.fontStrokeColor,t.lineJoin="round");for(var a=0;o>a;a++)this.options.fontStrokeWidth>0&&t.strokeText(s[a],e,i),t.fillText(s[a],e,i),i+=n},s.prototype._drawDashLine=function(t){t.strokeStyle=this._getColor(t),t.lineWidth=this._getLineWidth();var e=null;if(void 0!==t.setLineDash){t.save();var i=[0];i=void 0!==this.options.dash.length&&void 0!==this.options.dash.gap?[this.options.dash.length,this.options.dash.gap]:[5,5],t.setLineDash(i),t.lineDashOffset=0,e=this._line(t),t.setLineDash([0]),t.lineDashOffset=0,t.restore()}else t.beginPath(),t.lineCap="round",void 0!==this.options.dash.altLength?t.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y,[this.options.dash.length,this.options.dash.gap,this.options.dash.altLength,this.options.dash.gap]):void 0!==this.options.dash.length&&void 0!==this.options.dash.gap?t.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y,[this.options.dash.length,this.options.dash.gap]):(t.moveTo(this.from.x,this.from.y),t.lineTo(this.to.x,this.to.y)),t.stroke();if(this.label){var s;if(1==this.options.smoothCurves.enabled&&null!=e){var o=.5*(.5*(this.from.x+e.x)+.5*(this.to.x+e.x)),n=.5*(.5*(this.from.y+e.y)+.5*(this.to.y+e.y));s={x:o,y:n}}else s=this._pointOnLine(.5);this._label(t,this.label,s.x,s.y)}},s.prototype._pointOnLine=function(t){return{x:(1-t)*this.from.x+t*this.to.x,y:(1-t)*this.from.y+t*this.to.y}},s.prototype._pointOnCircle=function(t,e,i,s){var o=2*(s-3/8)*Math.PI;return{x:t+i*Math.cos(o),y:e-i*Math.sin(o)}},s.prototype._drawArrowCenter=function(t){var e;if(t.strokeStyle=this._getColor(t),t.fillStyle=t.strokeStyle,t.lineWidth=this._getLineWidth(),this.from!=this.to){var i=this._line(t),s=Math.atan2(this.to.y-this.from.y,this.to.x-this.from.x),o=(10+5*this.options.width)*this.options.arrowScaleFactor;if(1==this.options.smoothCurves.enabled&&null!=i){var n=.5*(.5*(this.from.x+i.x)+.5*(this.to.x+i.x)),r=.5*(.5*(this.from.y+i.y)+.5*(this.to.y+i.y));e={x:n,y:r}}else e=this._pointOnLine(.5);t.arrow(e.x,e.y,s,o),t.fill(),t.stroke(),this.label&&this._label(t,this.label,e.x,e.y)}else{var a,h,d=.25*Math.max(100,this.physics.springLength),l=this.from;l.width||l.resize(t),l.width>l.height?(a=l.x+.5*l.width,h=l.y-d):(a=l.x+d,h=l.y-.5*l.height),this._circle(t,a,h,d);var s=.2*Math.PI,o=(10+5*this.options.width)*this.options.arrowScaleFactor;e=this._pointOnCircle(a,h,d,.5),t.arrow(e.x,e.y,s,o),t.fill(),t.stroke(),this.label&&(e=this._pointOnCircle(a,h,d,.5),this._label(t,this.label,e.x,e.y))}},s.prototype._pointOnBezier=function(t){var e=this._getViaCoordinates(),i=Math.pow(1-t,2)*this.from.x+2*t*(1-t)*e.x+Math.pow(t,2)*this.to.x,s=Math.pow(1-t,2)*this.from.y+2*t*(1-t)*e.y+Math.pow(t,2)*this.to.y;return{x:i,y:s}},s.prototype._findBorderPosition=function(t,e){var i,s,o,n,r,a=10,h=0,d=0,l=1,c=.2,p=this.to;for(1==t&&(p=this.from);l>=d&&a>h;){var u=.5*(d+l);if(i=this._pointOnBezier(u),s=Math.atan2(p.y-i.y,p.x-i.x),o=p.distanceToBorder(e,s),n=Math.sqrt(Math.pow(i.x-p.x,2)+Math.pow(i.y-p.y,2)),r=o-n,Math.abs(r)r?0==t?d=u:l=u:0==t?l=u:d=u,h++}return i.t=u,i},s.prototype._drawArrow=function(t){t.strokeStyle=this._getColor(t),t.fillStyle=t.strokeStyle,t.lineWidth=this._getLineWidth();var e,i,s;if(this.from!=this.to){if(this._line(t),1==this.options.smoothCurves.enabled){var o=this._getViaCoordinates();s=this._findBorderPosition(!1,t);var n=this._pointOnBezier(Math.max(0,s.t-.1));e=Math.atan2(s.y-n.y,s.x-n.x)}else{e=Math.atan2(this.to.y-this.from.y,this.to.x-this.from.x);var r=this.to.x-this.from.x,a=this.to.y-this.from.y,h=Math.sqrt(r*r+a*a),d=this.to.distanceToBorder(t,e),l=(h-d)/h;s={},s.x=(1-l)*this.from.x+l*this.to.x,s.y=(1-l)*this.from.y+l*this.to.y}if(i=(10+5*this.options.width)*this.options.arrowScaleFactor,t.arrow(s.x,s.y,e,i),t.fill(),t.stroke(),this.label){var c;c=1==this.options.smoothCurves.enabled&&null!=o?this._pointOnBezier(.5):this._pointOnLine(.5),this._label(t,this.label,c.x,c.y)}}else{var p,u,m,f=this.from,g=.25*Math.max(100,this.physics.springLength);f.width||f.resize(t),f.width>f.height?(p=f.x+.5*f.width,u=f.y-g,m={x:p,y:f.y,angle:.9*Math.PI}):(p=f.x+g,u=f.y-.5*f.height,m={x:f.x,y:u,angle:.6*Math.PI}),t.beginPath(),t.arc(p,u,g,0,2*Math.PI,!1),t.stroke();var i=(10+5*this.options.width)*this.options.arrowScaleFactor;t.arrow(m.x,m.y,m.angle,i),t.fill(),t.stroke(),this.label&&(c=this._pointOnCircle(p,u,g,.5),this._label(t,this.label,c.x,c.y))}},s.prototype._getDistanceToEdge=function(t,e,i,s,o,n){var r=0;if(this.from!=this.to)if(1==this.options.smoothCurves.enabled){var a,h;if(1==this.options.smoothCurves.enabled&&1==this.options.smoothCurves.dynamic)a=this.via.x,h=this.via.y;else{var d=this._getViaCoordinates();a=d.x,h=d.y}var l,c,p,u,m,f,g,v=1e9;for(c=0;10>c;c++)p=.1*c,u=Math.pow(1-p,2)*t+2*p*(1-p)*a+Math.pow(p,2)*i,m=Math.pow(1-p,2)*e+2*p*(1-p)*h+Math.pow(p,2)*s,c>0&&(l=this._getDistanceToLine(f,g,u,m,o,n),v=v>l?l:v),f=u,g=m;r=v}else r=this._getDistanceToLine(t,e,i,s,o,n);else{var u,m,y,b,_=.25*this.physics.springLength,x=this.from;x.width>x.height?(u=x.x+.5*x.width,m=x.y-_):(u=x.x+_,m=x.y-.5*x.height),y=u-o,b=m-n,r=Math.abs(Math.sqrt(y*y+b*b)-_)}return this.labelDimensions.lefto&&this.labelDimensions.topn?0:r},s.prototype._getDistanceToLine=function(t,e,i,s,o,n){var r=i-t,a=s-e,h=r*r+a*a,d=((o-t)*r+(n-e)*a)/h;d>1?d=1:0>d&&(d=0);var l=t+d*r,c=e+d*a,p=l-o,u=c-n;return Math.sqrt(p*p+u*u)},s.prototype.setScale=function(t){this.networkScaleInv=1/t},s.prototype.select=function(){this.selected=!0},s.prototype.unselect=function(){this.selected=!1},s.prototype.positionBezierNode=function(){null!==this.via&&null!==this.from&&null!==this.to?(this.via.x=.5*(this.from.x+this.to.x),this.via.y=.5*(this.from.y+this.to.y)):null!==this.via&&(this.via.x=0,this.via.y=0)},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:7,borderWidth:2,borderWidthSelected:2},physics:{damping:0},clustering:{maxNodeSizeIncrements:0,nodeScaling:{width:0,height:0,radius:0}}};this.controlNodes.from=new n({id:e,shape:"dot",color:{background:"#ff0000",border:"#3c3c3c",highlight:{background:"#07f968"}}},{},{},s),this.controlNodes.to=new n({id:i,shape:"dot",color:{background:"#ff0000",border:"#3c3c3c",highlight:{background:"#07f968"}}},{},{},s)}this.controlNodes.positions={},0==this.controlNodes.from.selected&&(this.controlNodes.positions.from=this.getControlNodeFromPosition(t),this.controlNodes.from.x=this.controlNodes.positions.from.x,this.controlNodes.from.y=this.controlNodes.positions.from.y),0==this.controlNodes.to.selected&&(this.controlNodes.positions.to=this.getControlNodeToPosition(t),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.fromBackup=this.from,this.toBackup=this.to,this.controlNodesEnabled=!0},s.prototype._disableControlNodes=function(){this.fromId=this.from.id,this.toId=this.to.id,this.fromId!=this.fromBackup.id?this.fromBackup.detachEdge(this):this.toId!=this.toBackup.id&&this.toBackup.detachEdge(this),this.fromBackup=null,this.toBackup=null,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.getControlNodeFromPosition=function(t){var e;if(1==this.options.smoothCurves.enabled)e=this._findBorderPosition(!0,t);else{var 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;e={},e.x=a*this.from.x+(1-a)*this.to.x,e.y=a*this.from.y+(1-a)*this.to.y}return e},s.prototype.getControlNodeToPosition=function(t){var e;if(1==this.options.smoothCurves.enabled)e=this._findBorderPosition(!1,t);else{var 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.to.distanceToBorder(t,i),a=(n-r)/n;e={},e.x=(1-a)*this.from.x+a*this.to.x,e.y=(1-a)*this.from.y+a*this.to.y}return e},t.exports=s},function(t,e,i){function s(){this.clear(),this.defaultIndex=0,this.groupsArray=[],this.groupIndex=0,this.useDefaultGroups=!0}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"}},{border:"#990000",background:"#EE0000",highlight:{border:"#BB0000",background:"#FF3333"},hover:{border:"#BB0000",background:"#FF3333"}},{border:"#FF6000",background:"#FF6000",highlight:{border:"#FF6000",background:"#FF6000"},hover:{border:"#FF6000",background:"#FF6000"}},{border:"#97C2FC",background:"#2B7CE9",highlight:{border:"#D2E5FF",background:"#2B7CE9"},hover:{border:"#D2E5FF",background:"#2B7CE9"}},{border:"#399605",background:"#255C03",highlight:{border:"#399605",background:"#255C03"},hover:{border:"#399605",background:"#255C03"}},{border:"#B70054",background:"#FF007E",highlight:{border:"#B70054",background:"#FF007E"},hover:{border:"#B70054",background:"#FF007E"}},{border:"#AD85E4",background:"#7C29F0",highlight:{border:"#D3BDF0",background:"#7C29F0"},hover:{border:"#D3BDF0",background:"#7C29F0"}},{border:"#4557FA",background:"#000EA1",highlight:{border:"#6E6EFD",background:"#000EA1"},hover:{border:"#6E6EFD",background:"#000EA1"}},{border:"#FFC0CB",background:"#FD5A77",highlight:{border:"#FFD1D9",background:"#FD5A77"},hover:{border:"#FFD1D9",background:"#FD5A77"}},{border:"#C2FABC",background:"#74D66A",highlight:{border:"#E6FFE3",background:"#74D66A"},hover:{border:"#E6FFE3",background:"#74D66A"}},{border:"#EE0000",background:"#990000",highlight:{border:"#FF3333",background:"#BB0000"},hover:{border:"#FF3333",background:"#BB0000"}}],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)if(this.useDefaultGroups===!1&&this.groupsArray.length>0){var i=this.groupIndex%this.groupsArray.length;this.groupIndex++,e={},e.color=this.groups[this.groupsArray[i]],this.groups[t]=e}else{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,this.groupsArray.push(t),e},t.exports=s},function(t){function e(){this.images={},this.imageBroken={},this.callback=void 0}e.prototype.setOnloadCallback=function(t){this.callback=t},e.prototype.load=function(t,e){var i=this.images[t];if(void 0===i){var s=this;i=new Image,i.onload=function(){0==this.width&&(document.body.appendChild(this),this.width=this.offsetWidth,this.height=this.offsetHeight,document.body.removeChild(this)),s.callback&&(s.images[t]=i,s.callback(this))},i.onerror=function(){void 0===e?(console.error("Could not load image:",t),delete this.src,s.callback&&s.callback(this)):s.imageBroken[t]===!0?this.src==e?(console.error("Could not load brokenImage:",e),delete this.src,s.callback&&s.callback(this)):(console.error("Could not load image:",t),this.src=e):(console.error("Could not load image:",t),this.src=e,s.imageBroken[t]=!0)},i.src=t}return i},t.exports=e},function(t,e,i){function s(t,e,i,s){var n=o.selectiveBridgeObject(["nodes"],s);this.options=n.nodes,this.selected=!1,this.hover=!1,this.edges=[],this.dynamicEdges=[],this.reroutedEdges={},this.id=void 0,this.allowedToMoveX=!1,this.allowedToMoveY=!1,this.xFixed=!1,this.yFixed=!1,this.horizontalAlignLeft=!0,this.verticalAlignTop=!0,this.baseRadiusValue=s.nodes.radius,this.radiusFixed=!1,this.level=-1,this.preassignedLevel=!1,this.hierarchyEnumerated=!1,this.labelDimensions={top:0,left:0,width:0,height:0,yLine:0},this.boundingBox={top:0,left:0,right:0,bottom:0},this.imagelist=e,this.grouplist=i,this.fx=0,this.fy=0,this.vx=0,this.vy=0,this.x=null,this.y=null,this.predefinedPosition=!1,this.previousState={vx:0,vy:0,x:0,y:0},this.damping=s.physics.damping,this.fixedData={x:null,y:null},this.setProperties(t,n),this.resetCluster(),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.revertPosition=function(){this.x=this.previousState.x,this.y=this.previousState.y,this.vx=this.previousState.vx,this.vy=this.previousState.vy},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)},s.prototype.detachEdge=function(t){var e=this.edges.indexOf(t);-1!=e&&this.edges.splice(e,1),e=this.dynamicEdges.indexOf(t),-1!=e&&this.dynamicEdges.splice(e,1)},s.prototype.setProperties=function(t,e){if(t){var i=["borderWidth","borderWidthSelected","shape","image","brokenImage","radius","fontColor","fontSize","fontFace","fontFill","fontStrokeWidth","fontStrokeColor","group","mass","fontDrawThreshold","scaleFontWithValue","fontSizeMaxVisible","customScalingFunction","iconFontFace","icon","iconColor","iconSize"];if(o.selectiveDeepExtend(i,this.options,t),void 0!==t.id&&(this.id=t.id),void 0!==t.label&&(this.label=t.label,this.originalLabel=t.label),void 0!==t.title&&(this.title=t.title),void 0!==t.x&&(this.x=t.x,this.predefinedPosition=!0),void 0!==t.y&&(this.y=t.y,this.predefinedPosition=!0),void 0!==t.value&&(this.value=t.value),void 0!==t.level&&(this.level=t.level,this.preassignedLevel=!0),void 0!==t.horizontalAlignLeft&&(this.horizontalAlignLeft=t.horizontalAlignLeft),void 0!==t.verticalAlignTop&&(this.verticalAlignTop=t.verticalAlignTop),void 0!==t.triggerFunction&&(this.triggerFunction=t.triggerFunction),void 0===this.id)throw"Node must have an id";if("number"==typeof t.group||"string"==typeof t.group&&""!=t.group){var s=this.grouplist.get(t.group);o.deepExtend(this.options,s),this.options.color=o.parseColor(this.options.color)}if(void 0!==t.radius&&(this.baseRadiusValue=this.options.radius),void 0!==t.color&&(this.options.color=o.parseColor(t.color)),void 0!==this.options.image&&""!=this.options.image){if(!this.imagelist)throw"No imagelist provided";this.imageObj=this.imagelist.load(this.options.image,this.options.brokenImage)}switch(void 0!==t.allowedToMoveX?(this.xFixed=!t.allowedToMoveX,this.allowedToMoveX=t.allowedToMoveX):void 0!==t.x&&0==this.allowedToMoveX&&(this.xFixed=!0),void 0!==t.allowedToMoveY?(this.yFixed=!t.allowedToMoveY,this.allowedToMoveY=t.allowedToMoveY):void 0!==t.y&&0==this.allowedToMoveY&&(this.yFixed=!0),this.radiusFixed=this.radiusFixed||void 0!==t.radius,("image"===this.options.shape||"circularImage"===this.options.shape)&&(this.options.radiusMin=e.nodes.widthMin,this.options.radiusMax=e.nodes.widthMax),this.options.shape){case"database":this.draw=this._drawDatabase,this.resize=this._resizeDatabase;break;case"box":this.draw=this._drawBox,this.resize=this._resizeBox;break;case"circle":this.draw=this._drawCircle,this.resize=this._resizeCircle;break;case"ellipse":this.draw=this._drawEllipse,this.resize=this._resizeEllipse;break;case"image":this.draw=this._drawImage,this.resize=this._resizeImage;break;case"circularImage":this.draw=this._drawCircularImage,this.resize=this._resizeCircularImage;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;case"icon":this.draw=this._drawIcon,this.resize=this._resizeIcon;break;default:this.draw=this._drawEllipse,this.resize=this._resizeEllipse}this._reset()}},s.prototype.select=function(){this.selected=!0,this._reset()},s.prototype.unselect=function(){this.selected=!1,this._reset()},s.prototype.clearSizeCache=function(){this._reset() -},s.prototype._reset=function(){this.width=void 0,this.height=void 0},s.prototype.getTitle=function(){return"function"==typeof this.title?this.title():this.title},s.prototype.distanceToBorder=function(t,e){var i=1;switch(this.width||this.resize(t),this.options.shape){case"circle":case"dot":return this.options.radius+i;case"ellipse":var s=this.width/2,o=this.height/2,n=Math.sin(e)*s,r=Math.cos(e)*o;return s*o/Math.sqrt(n*n+r*r);case"box":case"image":case"text":default:return this.width?Math.min(Math.abs(this.width/2/Math.cos(e)),Math.abs(this.height/2/Math.sin(e)))+i:0}},s.prototype._setForce=function(t,e){this.fx=t,this.fy=e},s.prototype._addForce=function(t,e){this.fx+=t,this.fy+=e},s.prototype.storeState=function(){this.previousState.x=this.x,this.previousState.y=this.y,this.previousState.vx=this.vx,this.previousState.vy=this.vy},s.prototype.discreteStep=function(t){if(this.storeState(),this.xFixed)this.fx=0,this.vx=0;else{var e=this.damping*this.vx,i=(this.fx-e)/this.options.mass;this.vx+=i*t,this.x+=this.vx*t}if(this.yFixed)this.fy=0,this.vy=0;else{var s=this.damping*this.vy,o=(this.fy-s)/this.options.mass;this.vy+=o*t,this.y+=this.vy*t}},s.prototype.discreteStepLimited=function(t,e){if(this.storeState(),this.xFixed)this.fx=0,this.vx=0;else{var i=this.damping*this.vx,s=(this.fx-i)/this.options.mass;this.vx+=s*t,this.vx=Math.abs(this.vx)>e?this.vx>0?e:-e:this.vx,this.x+=this.vx*t}if(this.yFixed)this.fy=0,this.vy=0;else{var o=this.damping*this.vy,n=(this.fy-o)/this.options.mass;this.vy+=n*t,this.vy=Math.abs(this.vy)>e?this.vy>0?e:-e:this.vy,this.y+=this.vy*t}},s.prototype.isFixed=function(){return this.xFixed&&this.yFixed},s.prototype.isMoving=function(t){var e=Math.sqrt(Math.pow(this.vx,2)+Math.pow(this.vy,2));return e>t},s.prototype.isSelected=function(){return this.selected},s.prototype.getValue=function(){return this.value},s.prototype.getDistance=function(t,e){var i=this.x-t,s=this.y-e;return Math.sqrt(i*i+s*s)},s.prototype.setValueRange=function(t,e,i){if(!this.radiusFixed&&void 0!==this.value){var s=this.options.customScalingFunction(t,e,i,this.value),o=this.options.radiusMax-this.options.radiusMin;if(1==this.options.scaleFontWithValue){var n=this.options.fontSizeMax-this.options.fontSizeMin;this.options.fontSize=this.options.fontSizeMin+s*n}this.options.radius=this.options.radiusMin+s*o}this.baseRadiusValue=this.options.radius},s.prototype.draw=function(){throw"Draw method not initialized for node"},s.prototype.resize=function(){throw"Resize method not initialized for node"},s.prototype.isOverlappingWith=function(t){return this.leftt.left&&this.topt.top},s.prototype._resizeImage=function(){if(!this.width||!this.height){var t,e;if(this.value){this.options.radius=this.baseRadiusValue;var i=this.imageObj.height/this.imageObj.width;void 0!==i?(t=this.options.radius||this.imageObj.width,e=this.options.radius*i||this.imageObj.height):(t=0,e=0)}else t=this.imageObj.width,e=this.imageObj.height;this.width=t,this.height=e,this.growthIndicator=0,this.width>0&&this.height>0&&(this.width+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeWidthFactor,this.height+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeHeightFactor,this.options.radius+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeRadiusFactor,this.growthIndicator=this.width-t)}},s.prototype._drawImageAtPosition=function(t){if(0!=this.imageObj.width){if(this.clusterSize>1){var e=this.clusterSize>1?10:0;e*=this.networkScaleInv,e=Math.min(.2*this.width,e),t.globalAlpha=.5,t.drawImage(this.imageObj,this.left-e,this.top-e,this.width+2*e,this.height+2*e)}t.globalAlpha=1,t.drawImage(this.imageObj,this.left,this.top,this.width,this.height)}},s.prototype._drawImageLabel=function(t){var e,i=0;if(this.height){i=this.height/2;var s=this.getTextSize(t);s.lineCount>=1&&(i+=s.height/2,i+=3)}e=this.y+i,this._label(t,this.label,this.x,e,void 0)},s.prototype._drawImage=function(t){this._resizeImage(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,this._drawImageAtPosition(t),this.boundingBox.top=this.top,this.boundingBox.left=this.left,this.boundingBox.right=this.left+this.width,this.boundingBox.bottom=this.top+this.height,this._drawImageLabel(t),this.boundingBox.left=Math.min(this.boundingBox.left,this.labelDimensions.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelDimensions.left+this.labelDimensions.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelDimensions.height)},s.prototype._resizeCircularImage=function(t){if(this.imageObj.src&&this.imageObj.width&&this.imageObj.height)this._swapToImageResizeWhenImageLoaded&&(this.width=0,this.height=0,delete this._swapToImageResizeWhenImageLoaded),this._resizeImage(t);else if(!this.width){var e=2*this.options.radius;this.width=e,this.height=e,this.options.radius+=.5*Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeRadiusFactor,this.growthIndicator=this.options.radius-.5*e,this._swapToImageResizeWhenImageLoaded=!0}},s.prototype._drawCircularImage=function(t){this._resizeCircularImage(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2;var e=this.left+this.width/2,i=this.top+this.height/2,s=Math.abs(this.height/2);this._drawRawCircle(t,e,i,s),t.save(),t.circle(this.x,this.y,s),t.stroke(),t.clip(),this._drawImageAtPosition(t),t.restore(),this.boundingBox.top=this.y-this.options.radius,this.boundingBox.left=this.x-this.options.radius,this.boundingBox.right=this.x+this.options.radius,this.boundingBox.bottom=this.y+this.options.radius,this._drawImageLabel(t),this.boundingBox.left=Math.min(this.boundingBox.left,this.labelDimensions.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelDimensions.left+this.labelDimensions.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelDimensions.height)},s.prototype._resizeBox=function(t){if(!this.width){var e=5,i=this.getTextSize(t);this.width=i.width+2*e,this.height=i.height+2*e,this.width+=.5*Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeWidthFactor,this.height+=.5*Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeHeightFactor,this.growthIndicator=this.width-(i.width+2*e)}},s.prototype._drawBox=function(t){this._resizeBox(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2;var e=2.5,i=this.options.borderWidth,s=this.options.borderWidthSelected||2*this.options.borderWidth;t.strokeStyle=this.selected?this.options.color.highlight.border:this.hover?this.options.color.hover.border:this.options.color.border,this.clusterSize>1&&(t.lineWidth=(this.selected?s:i)+(this.clusterSize>1?e:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.roundRect(this.left-2*t.lineWidth,this.top-2*t.lineWidth,this.width+4*t.lineWidth,this.height+4*t.lineWidth,this.options.radius),t.stroke()),t.lineWidth=(this.selected?s:i)+(this.clusterSize>1?e:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.fillStyle=this.selected?this.options.color.highlight.background:this.hover?this.options.color.hover.background:this.options.color.background,t.roundRect(this.left,this.top,this.width,this.height,this.options.radius),t.fill(),t.stroke(),this.boundingBox.top=this.top,this.boundingBox.left=this.left,this.boundingBox.right=this.left+this.width,this.boundingBox.bottom=this.top+this.height,this._label(t,this.label,this.x,this.y)},s.prototype._resizeDatabase=function(t){if(!this.width){var e=5,i=this.getTextSize(t),s=i.width+2*e;this.width=s,this.height=s,this.width+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeWidthFactor,this.height+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeHeightFactor,this.options.radius+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeRadiusFactor,this.growthIndicator=this.width-s}},s.prototype._drawDatabase=function(t){this._resizeDatabase(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2;var e=2.5,i=this.options.borderWidth,s=this.options.borderWidthSelected||2*this.options.borderWidth;t.strokeStyle=this.selected?this.options.color.highlight.border:this.hover?this.options.color.hover.border:this.options.color.border,this.clusterSize>1&&(t.lineWidth=(this.selected?s:i)+(this.clusterSize>1?e:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.database(this.x-this.width/2-2*t.lineWidth,this.y-.5*this.height-2*t.lineWidth,this.width+4*t.lineWidth,this.height+4*t.lineWidth),t.stroke()),t.lineWidth=(this.selected?s:i)+(this.clusterSize>1?e:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.fillStyle=this.selected?this.options.color.highlight.background:this.hover?this.options.color.hover.background:this.options.color.background,t.database(this.x-this.width/2,this.y-.5*this.height,this.width,this.height),t.fill(),t.stroke(),this.boundingBox.top=this.top,this.boundingBox.left=this.left,this.boundingBox.right=this.left+this.width,this.boundingBox.bottom=this.top+this.height,this._label(t,this.label,this.x,this.y)},s.prototype._resizeCircle=function(t){if(!this.width){var e=5,i=this.getTextSize(t),s=Math.max(i.width,i.height)+2*e;this.options.radius=s/2,this.width=s,this.height=s,this.options.radius+=.5*Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeRadiusFactor,this.growthIndicator=this.options.radius-.5*s}},s.prototype._drawRawCircle=function(t,e,i,s){var o=2.5,n=this.options.borderWidth,r=this.options.borderWidthSelected||2*this.options.borderWidth;t.strokeStyle=this.selected?this.options.color.highlight.border:this.hover?this.options.color.hover.border:this.options.color.border,this.clusterSize>1&&(t.lineWidth=(this.selected?r:n)+(this.clusterSize>1?o:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.circle(e,i,s+2*t.lineWidth),t.stroke()),t.lineWidth=(this.selected?r:n)+(this.clusterSize>1?o:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.fillStyle=this.selected?this.options.color.highlight.background:this.hover?this.options.color.hover.background:this.options.color.background,t.circle(this.x,this.y,s),t.fill(),t.stroke()},s.prototype._drawCircle=function(t){this._resizeCircle(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,this._drawRawCircle(t,this.x,this.y,this.options.radius),this.boundingBox.top=this.y-this.options.radius,this.boundingBox.left=this.x-this.options.radius,this.boundingBox.right=this.x+this.options.radius,this.boundingBox.bottom=this.y+this.options.radius,this._label(t,this.label,this.x,this.y)},s.prototype._resizeEllipse=function(t){if(!this.width){var e=this.getTextSize(t);this.width=1.5*e.width,this.height=2*e.height,this.width1&&(t.lineWidth=(this.selected?s:i)+(this.clusterSize>1?e:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.ellipse(this.left-2*t.lineWidth,this.top-2*t.lineWidth,this.width+4*t.lineWidth,this.height+4*t.lineWidth),t.stroke()),t.lineWidth=(this.selected?s:i)+(this.clusterSize>1?e:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.fillStyle=this.selected?this.options.color.highlight.background:this.hover?this.options.color.hover.background:this.options.color.background,t.ellipse(this.left,this.top,this.width,this.height),t.fill(),t.stroke(),this.boundingBox.top=this.top,this.boundingBox.left=this.left,this.boundingBox.right=this.left+this.width,this.boundingBox.bottom=this.top+this.height,this._label(t,this.label,this.x,this.y)},s.prototype._drawDot=function(t){this._drawShape(t,"circle")},s.prototype._drawTriangle=function(t){this._drawShape(t,"triangle")},s.prototype._drawTriangleDown=function(t){this._drawShape(t,"triangleDown")},s.prototype._drawSquare=function(t){this._drawShape(t,"square")},s.prototype._drawStar=function(t){this._drawShape(t,"star")},s.prototype._resizeShape=function(){if(!this.width){this.options.radius=this.baseRadiusValue;var t=2*this.options.radius;this.width=t,this.height=t,this.width+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeWidthFactor,this.height+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeHeightFactor,this.options.radius+=.5*Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeRadiusFactor,this.growthIndicator=this.width-t}},s.prototype._drawShape=function(t,e){this._resizeShape(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2;var i=2.5,s=this.options.borderWidth,o=this.options.borderWidthSelected||2*this.options.borderWidth,n=2;switch(e){case"dot":n=2;break;case"square":n=2;break;case"triangle":n=3;break;case"triangleDown":n=3;break;case"star":n=4}t.strokeStyle=this.selected?this.options.color.highlight.border:this.hover?this.options.color.hover.border:this.options.color.border,this.clusterSize>1&&(t.lineWidth=(this.selected?o:s)+(this.clusterSize>1?i:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t[e](this.x,this.y,this.options.radius+n*t.lineWidth),t.stroke()),t.lineWidth=(this.selected?o:s)+(this.clusterSize>1?i:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.fillStyle=this.selected?this.options.color.highlight.background:this.hover?this.options.color.hover.background:this.options.color.background,t[e](this.x,this.y,this.options.radius),t.fill(),t.stroke(),this.boundingBox.top=this.y-this.options.radius,this.boundingBox.left=this.x-this.options.radius,this.boundingBox.right=this.x+this.options.radius,this.boundingBox.bottom=this.y+this.options.radius,this.label&&(this._label(t,this.label,this.x,this.y+this.height/2,void 0,"hanging",!0),this.boundingBox.left=Math.min(this.boundingBox.left,this.labelDimensions.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelDimensions.left+this.labelDimensions.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelDimensions.height))},s.prototype._resizeText=function(t){if(!this.width){var e=5,i=this.getTextSize(t);this.width=i.width+2*e,this.height=i.height+2*e,this.width+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeWidthFactor,this.height+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeHeightFactor,this.options.radius+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeRadiusFactor,this.growthIndicator=this.width-(i.width+2*e)}},s.prototype._drawText=function(t){this._resizeText(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,this._label(t,this.label,this.x,this.y),this.boundingBox.top=this.top,this.boundingBox.left=this.left,this.boundingBox.right=this.left+this.width,this.boundingBox.bottom=this.top+this.height},s.prototype._resizeIcon=function(){if(!this.width){var t=5,e={width:Number(this.options.iconSize),height:Number(this.options.iconSize)};this.width=e.width+2*t,this.height=e.height+2*t,this.width+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeWidthFactor,this.height+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeHeightFactor,this.options.radius+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeRadiusFactor,this.growthIndicator=this.width-(e.width+2*t)}},s.prototype._drawIcon=function(t){if(this._resizeIcon(t),this.options.iconSize=this.options.iconSize||50,this.left=this.x-this.width/2,this.top=this.y-this.height/2,this._icon(t),this.boundingBox.top=this.y-this.options.iconSize/2,this.boundingBox.left=this.x-this.options.iconSize/2,this.boundingBox.right=this.x+this.options.iconSize/2,this.boundingBox.bottom=this.y+this.options.iconSize/2,this.label){var e=5;this._label(t,this.label,this.x,this.y+this.height/2+e,"top",!0),this.boundingBox.left=Math.min(this.boundingBox.left,this.labelDimensions.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelDimensions.left+this.labelDimensions.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelDimensions.height)}},s.prototype._icon=function(t){var e=Number(this.options.iconSize)*this.networkScale;if(this.options.icon&&e>this.options.fontDrawThreshold-1){var i=Number(this.options.iconSize);t.font=(this.selected?"bold ":"")+i+"px "+this.options.iconFontFace,t.fillStyle=this.options.iconColor||"black",t.textAlign="center",t.textBaseline="middle",t.fillText(this.options.icon,this.x,this.y)}},s.prototype._label=function(t,e,i,s,n,r,a){var h=Number(this.options.fontSize)*this.networkScale;if(e&&h>=this.options.fontDrawThreshold-1){var d=Number(this.options.fontSize);h>=this.options.fontSizeMaxVisible&&(d=Number(this.options.fontSizeMaxVisible)*this.networkScaleInv);var l=this.options.fontColor||"#000000",c=this.options.fontStrokeColor;if(h<=this.options.fontDrawThreshold){var p=Math.max(0,Math.min(1,1-(this.options.fontDrawThreshold-h)));l=o.overrideOpacity(l,p),c=o.overrideOpacity(c,p)}t.font=(this.selected?"bold ":"")+d+"px "+this.options.fontFace;var u=e.split("\n"),m=u.length,f=s+(1-m)/2*d;1==a&&(f=s+(1-m)/(2*d));for(var g=t.measureText(u[0]).width,v=1;m>v;v++){var y=t.measureText(u[v]).width;g=y>g?y:g}var b=d*m,_=i-g/2,x=s-b/2;"hanging"==r&&(x+=.5*d,x+=4,f+=4),this.labelDimensions={top:x,left:_,width:g,height:b,yLine:f},void 0!==this.options.fontFill&&null!==this.options.fontFill&&"none"!==this.options.fontFill&&(t.fillStyle=this.options.fontFill,t.fillRect(_,x,g,b)),t.fillStyle=l,t.textAlign=n||"center",t.textBaseline=r||"middle",this.options.fontStrokeWidth>0&&(t.lineWidth=this.options.fontStrokeWidth,t.strokeStyle=c,t.lineJoin="round");for(var v=0;m>v;v++)this.options.fontStrokeWidth&&t.strokeText(u[v],i,f),t.fillText(u[v],i,f),f+=d}},s.prototype.getTextSize=function(t){if(void 0!==this.label){var e=Number(this.options.fontSize);e*this.networkScale>this.options.fontSizeMaxVisible&&(e=Number(this.options.fontSizeMaxVisible)*this.networkScaleInv),t.font=(this.selected?"bold ":"")+e+"px "+this.options.fontFace;for(var i=this.label.split("\n"),s=(e+4)*i.length,o=0,n=0,r=i.length;r>n;n++)o=Math.max(o,t.measureText(i[n]).width);return{width:o,height:s,lineCount:i.length}}return{width:0,height:0,lineCount: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(N=D.NULL,k="";" "==E||" "==E||"\n"==E||"\r"==E;)o();do{var t=!1;if("#"==E){for(var e=O-1;" "==T.charAt(e)||" "==T.charAt(e);)e--;if("\n"==T.charAt(e)||""==T.charAt(e)){for(;""!=E&&"\n"!=E;)o();t=!0}}if("/"==E&&"/"==n()){for(;""!=E&&"\n"!=E;)o();t=!0}if("/"==E&&"*"==n()){for(;""!=E;){if("*"==E&&"/"==n()){o(),o();break}o()}t=!0}for(;" "==E||" "==E||"\n"==E||"\r"==E;)o()}while(t);if(""==E)return void(N=D.DELIMITER);var i=E+n();if(C[i])return N=D.DELIMITER,k=i,o(),void o();if(C[E])return N=D.DELIMITER,k=E,void o();if(r(E)||"-"==E){for(k+=E,o();r(E);)k+=E,o();return"false"==k?k=!1:"true"==k?k=!0:isNaN(Number(k))||(k=Number(k)),void(N=D.IDENTIFIER)}if('"'==E){for(o();""!=E&&('"'!=E||'"'==E&&'"'==n());)k+=E,'"'==E&&o(),o();if('"'!=E)throw x('End of string " expected');return o(),void(N=D.IDENTIFIER)}for(N=D.UNKNOWN;""!=E;)k+=E,o();throw new SyntaxError('Syntax error in part "'+w(k,30)+'"')}function u(){var t={};if(s(),p(),"strict"==k&&(t.strict=!0,p()),("graph"==k||"digraph"==k)&&(t.type=k,p()),N==D.IDENTIFIER&&(t.id=k,p()),"{"!=k)throw x("Angle bracket { expected");if(p(),m(t),"}"!=k)throw x("Angle bracket } expected");if(p(),""!==k)throw x("End of file expected");return p(),delete t.node,delete t.edge,delete t.graph,t}function m(t){for(;""!==k&&"}"!=k;)f(t),";"==k&&p()}function f(t){var e=g(t);if(e)return void b(t,e);var i=v(t);if(!i){if(N!=D.IDENTIFIER)throw x("Identifier expected");var s=k;if(p(),"="==k){if(p(),N!=D.IDENTIFIER)throw x("Identifier expected");t[s]=k,p()}else y(t,s)}}function g(t){var e=null;if("subgraph"==k&&(e={},e.type="subgraph",p(),N==D.IDENTIFIER&&(e.id=k,p())),"{"==k){if(p(),e||(e={}),e.parent=t,e.node=t.node,e.edge=t.edge,e.graph=t.graph,m(e),"}"!=k)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"==k?(p(),t.node=_(),"node"):"edge"==k?(p(),t.edge=_(),"edge"):"graph"==k?(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(;"->"==k||"--"==k;){var i,s=k;p();var o=g(t);if(o)i=o;else{if(N!=D.IDENTIFIER)throw x("Identifier or subgraph expected");i=k,d(t,{id:i}),p()}var n=_(),r=c(t,e,i,s,n);l(t,r),e=i}}function _(){for(var t=null;"["==k;){for(p(),t={};""!==k&&"]"!=k;){if(N!=D.IDENTIFIER)throw x("Attribute name expected");var e=k;if(p(),"="!=k)throw x("Equal sign = expected");if(p(),N!=D.IDENTIFIER)throw x("Attribute value expected");var i=k;h(t,e,i),p(),","==k&&p()}if("]"!=k)throw x("Bracket ] expected");p()}return t}function x(t){return new SyntaxError(t+', got "'+w(k,30)+'" (char '+O+")")}function w(t,e){return t.length<=e?t:t.substr(0,27)+"..."}function S(t,e,i){Array.isArray(t)?t.forEach(function(t){Array.isArray(e)?e.forEach(function(e){i(t,e)}):i(t,e)}):Array.isArray(e)?e.forEach(function(e){i(t,e)}):i(t,e)}function M(t){var e=i(t),s={nodes:[],edges:[],options:{}};if(e.nodes&&e.nodes.forEach(function(t){var e={id:t.id,label:String(t.label||t.id)};a(e,t.attr),e.image&&(e.shape="image"),s.nodes.push(e)}),e.edges){var o=function(t){var e={from:t.from,to:t.to};return a(e,t.attr),e.style="->"==t.type?"arrow":"line",e};e.edges.forEach(function(t){var e,i;e=t.from instanceof Object?t.from.nodes:{id:t.from},i=t.to instanceof Object?t.to.nodes:{id:t.to},t.from instanceof Object&&t.from.edges&&t.from.edges.forEach(function(t){var e=o(t);s.edges.push(e)}),S(e,i,function(e,i){var n=c(s,e.id,i.id,t.type,t.attr),r=o(n);s.edges.push(r)}),t.to instanceof Object&&t.to.edges&&t.to.edges.forEach(function(t){var e=o(t);s.edges.push(e)})})}return e.attr&&(s.options=e.attr),s}var D={NULL:0,DELIMITER:1,IDENTIFIER:2,UNKNOWN:3},C={"{":!0,"}":!0,"[":!0,"]":!0,";":!0,"=":!0,",":!0,"->":!0,"--":!0},T="",O=0,E="",k="",N=D.NULL,I=/[a-zA-Z_0-9.:#]/;e.parseDOT=i,e.DOTToGraph=M},function(t,e){function i(t,e){var i=[],s=[];this.options={edges:{inheritColor:!0},nodes:{allowedToMove:!1,parseColor:!1}},void 0!==e&&(this.options.nodes.allowedToMove=e.allowedToMove|!1,this.options.nodes.parseColor=e.parseColor|!1,this.options.edges.inheritColor=e.inheritColor|!0);for(var o=t.edges,n=t.nodes,r=0;r=s&&(s=864e5),e=new Date(e.valueOf()-.05*s),i=new Date(i.valueOf()+.05*s)}return{start:e,end:i}},s.prototype.setWindow=function(t,e,i){var s;if(1==arguments.length){var o=arguments[0];s=void 0!==o.animate?o.animate:!0,this.range.setRange(o.start,o.end,s)}else s=i&&void 0!==i.animate?i.animate:!0,this.range.setRange(t,e,s)},s.prototype.moveTo=function(t,e){var i=this.range.end-this.range.start,s=r.convert(t,"Date").valueOf(),o=s-i/2,n=s+i/2,a=e&&void 0!==e.animate?e.animate:!0;this.range.setRange(o,n,a)},s.prototype.getWindow=function(){var t=this.range.getRange();return{start:new Date(t.start),end:new Date(t.end)}},s.prototype.redraw=function(){this._redraw()},s.prototype._redraw=function(){var t=!1,e=this.options,i=this.props,s=this.dom;if(s){h.updateHiddenDates(this.body,this.options.hiddenDates),"top"==e.orientation?(r.addClassName(s.root,"top"),r.removeClassName(s.root,"bottom")):(r.removeClassName(s.root,"top"),r.addClassName(s.root,"bottom")),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;0===s.centerContainer.clientHeight&&(i.border.left=i.border.top,i.border.right=i.border.left),0===s.root.clientHeight&&(n=o),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),d=i.top.height+a+i.bottom.height+o+i.border.top+i.border.bottom;s.root.style.height=r.option.asSize(e.height,d+"px"),i.root.height=s.root.offsetHeight,i.background.height=i.root.height-o;var l=i.root.height-i.top.height-i.bottom.height-o;i.centerContainer.height=l,i.leftContainer.height=l,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 c=i.root.width-i.left.width-i.right.width-n;i.center.width=c,i.centerContainer.width=c,i.top.width=c,i.bottom.width=c,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+i.border.left+"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 p=this.props.scrollTop;"bottom"==e.orientation&&(p+=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=p+"px",s.left.style.left="0",s.left.style.top=p+"px",s.right.style.left="0",s.right.style.top=p+"px";var u=0==this.props.scrollTop?"hidden":"",m=this.props.scrollTop==this.props.scrollTopMin?"hidden":"";if(s.shadowTop.style.visibility=u,s.shadowBottom.style.visibility=m,s.shadowTopLeft.style.visibility=u,s.shadowBottomLeft.style.visibility=m,s.shadowTopRight.style.visibility=u,s.shadowBottomRight.style.visibility=m,this.components.forEach(function(e){t=e.redraw()||t}),t){var f=3;this.redrawCount0&&(this.props.scrollTop=0),this.props.scrollTops;s++){var o=s%2===0?1.3*i:.5*i;this.lineTo(t+o*Math.sin(2*s*Math.PI/10),e-o*Math.cos(2*s*Math.PI/10))}this.closePath()},CanvasRenderingContext2D.prototype.roundRect=function(t,e,i,s,o){var n=Math.PI/180;0>i-2*o&&(o=i/2),0>s-2*o&&(o=s/2),this.beginPath(),this.moveTo(t+o,e),this.lineTo(t+i-o,e),this.arc(t+i-o,e+o,o,270*n,360*n,!1),this.lineTo(t+i,e+s-o),this.arc(t+i-o,e+s-o,o,0,90*n,!1),this.lineTo(t+o,e+s),this.arc(t+o,e+s-o,o,90*n,180*n,!1),this.lineTo(t,e+o),this.arc(t+o,e+o,o,180*n,270*n,!1)},CanvasRenderingContext2D.prototype.ellipse=function(t,e,i,s){var o=.5522848,n=i/2*o,r=s/2*o,a=t+i,h=e+s,d=t+i/2,l=e+s/2;this.beginPath(),this.moveTo(t,l),this.bezierCurveTo(t,l-r,d-n,e,d,e),this.bezierCurveTo(d+n,e,a,l-r,a,l),this.bezierCurveTo(a,l+r,d+n,h,d,h),this.bezierCurveTo(d-n,h,t,l+r,t,l)},CanvasRenderingContext2D.prototype.database=function(t,e,i,s){var o=1/3,n=i,r=s*o,a=.5522848,h=n/2*a,d=r/2*a,l=t+n,c=e+r,p=t+n/2,u=e+r/2,m=e+(s-r/2),f=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,f,p,f),this.bezierCurveTo(p-h,f,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){function s(t,e){this.groupId=t,this.options=e}{var o=i(2);i(53)}s.prototype.getYRange=function(t){if("stack"!=this.options.barChart.handleOverlap){for(var e=t[0].y,i=t[0].y,s=0;st[s].y?t[s].y:e,i=i0&&(n=Math.min(n,Math.abs(c[d-1].x-r))),a=s._getSafeDrawData(n,h,m);else{var g=d+(p[r].amount-p[r].resolved),v=d-(p[r].resolved+1);g0&&(n=Math.min(n,Math.abs(c[v].x-r))),a=s._getSafeDrawData(n,h,m),p[r].resolved+=1,"stack"==h.options.barChart.handleOverlap?(f=p[r].accumulated,p[r].accumulated+=h.zeroPosition-c[d].y):"sideBySide"==h.options.barChart.handleOverlap&&(a.width=a.width/p[r].amount,a.offset+=p[r].resolved*a.width-.5*a.width*(p[r].amount+1),"left"==h.options.barChart.align?a.offset-=.5*a.width:"right"==h.options.barChart.align&&(a.offset+=.5*a.width))}o.drawBar(c[d].x+a.offset,c[d].y-f,a.width,h.zeroPosition-c[d].y,h.className+" bar",i.svgElements,i.svg),1==h.options.drawPoints.enabled&&o.drawPoint(c[d].x+a.offset,c[d].y,h,i.svgElements,i.svg)}},s._getDataIntersections=function(t,e){for(var i,s=0;s0&&(i=Math.min(i,Math.abs(e[s-1].x-e[s].x))),0==i&&(void 0===t[e[s].x]&&(t[e[s].x]={amount:0,resolved:0,accumulated:0}),t[e[s].x].amount+=1)},s._getSafeDrawData=function(t,e,i){var s,o;return t0?(s=i>t?i:t,o=0,"left"==e.options.barChart.align?o-=.5*t:"right"==e.options.barChart.align&&(o+=.5*t)):(s=e.options.barChart.width,o=0,"left"==e.options.barChart.align?o-=.5*e.options.barChart.width:"right"==e.options.barChart.align&&(o+=.5*e.options.barChart.width)),{width:s,offset:o}},s.getStackedBarYRange=function(t,e,i,o,n){if(t.length>0){t.sort(function(t,e){return t.x==e.x?t.groupId-e.groupId:t.x-e.x});var r={};s._getDataIntersections(r,t),e[o]=s._getStackedBarYRange(r,t),e[o].yAxisOrientation=n,i.push(o)}},s._getStackedBarYRange=function(t,e){for(var i,s=e[0].y,o=e[0].y,n=0;ne[n].y?e[n].y:s,o=ot[r].accumulated?t[r].accumulated:s,o=ot[s].y?t[s].y:e,i=i0){var r,a,h=Number(i.svg.style.height.replace("px",""));if(r=o.getSVGElement("path",i.svgElements,i.svg),r.setAttributeNS(null,"class",e.className),void 0!==e.style&&r.setAttributeNS(null,"style",e.style),a=1==e.options.catmullRom.enabled?s._catmullRom(t,e):s._linear(t),1==e.options.shaded.enabled){var d,l=o.getSVGElement("path",i.svgElements,i.svg);d="top"==e.options.shaded.orientation?"M"+t[0].x+",0 "+a+"L"+t[t.length-1].x+",0":"M"+t[0].x+","+h+" "+a+"L"+t[t.length-1].x+","+h,l.setAttributeNS(null,"class",e.className+" fill"),void 0!==e.options.shaded.style&&l.setAttributeNS(null,"style",e.options.shaded.style),l.setAttributeNS(null,"d",d)}r.setAttributeNS(null,"d","M"+a),1==e.options.drawPoints.enabled&&n.draw(t,e,i)}},s._catmullRomUniform=function(t){for(var e,i,s,o,n,r,a=Math.round(t[0].x)+","+Math.round(t[0].y)+" ",h=1/6,d=t.length,l=0;d-1>l;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._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,f,g,v,y,b,_,x,w=Math.round(t[0].x)+","+Math.round(t[0].y)+" ",S=t.length,M=0;S-1>M;M++)s=0==M?t[0]:t[M-1],o=t[M],n=t[M+1],r=S>M+2?t[M+2]:n,d=Math.sqrt(Math.pow(s.x-o.x,2)+Math.pow(s.y-o.y,2)),l=Math.sqrt(Math.pow(o.x-n.x,2)+Math.pow(o.y-n.y,2)),c=Math.sqrt(Math.pow(n.x-r.x,2)+Math.pow(n.y-r.y,2)),g=Math.pow(c,i),y=Math.pow(c,2*i),v=Math.pow(l,i),b=Math.pow(l,2*i),x=Math.pow(d,i),_=Math.pow(d,2*i),p=2*_+3*x*v+b,u=2*y+3*g*v+b,m=3*x*(x+v),m>0&&(m=1/m),f=3*g*(g+v),f>0&&(f=1/f),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)*f,y:(y*o.y+u*n.y-b*r.y)*f},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._linear=function(t){for(var e="",i=0;it[s].y?t[s].y:e,i=is;++s)i[s].apply(this,e)}return this},e.prototype.listeners=function(t){return this._callbacks=this._callbacks||{},this._callbacks[t]||[]},e.prototype.hasListeners=function(t){return!!this.listeners(t).length}},function(t,e,i){var s;!function(o,n){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 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",f=a.POINTER_PEN="pen",g=a.EVENT_START="start",v=a.EVENT_MOVE="move",y=a.EVENT_END="end",b=a.EVENT_RELEASE="release",_=a.EVENT_TOUCH="touch";a.READY=!1,a.plugins=a.plugins||{},a.gestures=a.gestures||{};var x=a.utils={extend:function(t,e,i){for(var s in e)!e.hasOwnProperty(s)||t[s]!==n&&i||(t[s]=e[s]);return t},on:function(t,e,i){t.addEventListener(e,i,!1)},off:function(t,e,i){t.removeEventListener(e,i,!1)},each:function(t,e,i){var s,o;if("forEach"in t)t.forEach(e,i);else if(t.length!==n){for(s=0,o=t.length;o>s;s++)if(e.call(i,t[s],s,t)===!1)return}else for(s in t)if(t.hasOwnProperty(s)&&e.call(i,t[s],s,t)===!1)return},inStr:function(t,e){return t.indexOf(e)>-1},inArray:function(t,e){if(t.indexOf){var i=t.indexOf(e);return-1===i?!1:i}for(var s=0,o=t.length;o>s;s++)if(t[s]===e)return s;return!1},toArray:function(t){return Array.prototype.slice.call(t,0)},hasParent:function(t,e){for(;t;){if(t==e)return!0;t=t.parentNode}return!1},getCenter:function(t){var e=[],i=[],s=[],o=[],n=Math.min,r=Math.max;return 1===t.length?{pageX:t[0].pageX,pageY:t[0].pageY,clientX:t[0].clientX,clientY:t[0].clientY}:(x.each(t,function(t){e.push(t.pageX),i.push(t.pageY),s.push(t.clientX),o.push(t.clientY)}),{pageX:(n.apply(Math,e)+r.apply(Math,e))/2,pageY:(n.apply(Math,i)+r.apply(Math,i))/2,clientX:(n.apply(Math,s)+r.apply(Math,s))/2,clientY:(n.apply(Math,o)+r.apply(Math,o))/2})},getVelocity:function(t,e,i){return{x:Math.abs(e/t)||0,y:Math.abs(i/t)||0}},getAngle:function(t,e){var i=e.clientX-t.clientX,s=e.clientY-t.clientY;return 180*Math.atan2(s,i)/Math.PI},getDirection:function(t,e){var i=Math.abs(t.clientX-e.clientX),s=Math.abs(t.clientY-e.clientY);return i>=s?t.clientX-e.clientX>0?l:p:t.clientY-e.clientY>0?c:d},getDistance:function(t,e){var i=e.clientX-t.clientX,s=e.clientY-t.clientY;return Math.sqrt(i*i+s*s)},getScale:function(t,e){return t.length>=2&&e.length>=2?this.getDistance(e[0],e[1])/this.getDistance(t[0],t[1]):1},getRotation:function(t,e){return t.length>=2&&e.length>=2?this.getAngle(e[1],e[0])-this.getAngle(t[1],t[0]):0},isVertical:function(t){return t==c||t==d},setPrefixedCss:function(t,e,i,s){var o=["","Webkit","Moz","O","ms"];e=x.toCamelCase(e);for(var n=0;n0&&this.started&&(r=v),this.started=!0;var d=this.collectEventData(i,r,o,t);return e!=y&&s.call(M,d),a&&(d.changedLength=h,d.eventType=a,s.call(M,d),d.eventType=r,delete d.changedLength),r==y&&(s.call(M,d),this.started=!1),r},determineEventTypes:function(){var t;return t=a.HAS_POINTEREVENTS?o.PointerEvent?["pointerdown","pointermove","pointerup pointercancel lostpointercapture"]:["MSPointerDown","MSPointerMove","MSPointerUp MSPointerCancel MSLostPointerCapture"]:a.NO_MOUSEEVENTS?["touchstart","touchmove","touchend touchcancel"]:["touchstart mousedown","touchmove mousemove","touchend touchcancel mouseup"],h[g]=t[0],h[v]=t[1],h[y]=t[2],h},getTouchList:function(t,e){if(a.HAS_POINTEREVENTS)return S.getTouchList();if(t.touches){if(e==v)return t.touches;var i=[],s=[].concat(x.toArray(t.touches),x.toArray(t.changedTouches)),o=[];return x.each(s,function(t){x.inArray(i,t.identifier)===!1&&o.push(t),i.push(t.identifier)}),o}return t.identifier=1,[t]},collectEventData:function(t,e,i,s){var o=m;return x.inStr(s.type,"mouse")||S.matchType(u,s)?o=u:S.matchType(f,s)&&(o=f),{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[f]=i===(e.MSPOINTER_TYPE_PEN||f),s[t]},reset:function(){this.pointers={}}},M=a.detection={gestures:[],current:null,previous:null,stopped:!1,startDetect:function(t,e){this.current||(this.stopped=!1,this.current={inst:t,startEvent:x.extend({},e),lastEvent:!1,lastCalcEvent:!1,futureCalcEvent:!1,lastCalcData:{},name:""},this.detect(e))},detect:function(t){if(this.current&&!this.stopped){t=this.extendEventData(t);var e=this.current.inst,i=e.options;return x.each(this.gestures,function(s){!this.stopped&&e.enabled&&i[s.name]&&s.handler.call(s,t,e)},this),this.current&&(this.current.lastEvent=t),t.eventType==y&&this.stopDetect(),t}},stopDetect:function(){this.previous=x.extend({},this.current),this.current=null,this.stopped=!0},getCalculatedData:function(t,e,i,s,o){var n=this.current,r=!1,h=n.lastCalcEvent,d=n.lastCalcData;h&&t.timeStamp-h.timeStamp>a.CALCULATE_INTERVAL&&(e=h.center,i=t.timeStamp-h.timeStamp,s=t.center.clientX-h.center.clientX,o=t.center.clientY-h.center.clientY,r=!0),(t.eventType==_||t.eventType==b)&&(n.futureCalcEvent=t),(!n.lastCalcEvent||r)&&(d.velocity=x.getVelocity(i,s,o),d.angle=x.getAngle(e,t.center),d.direction=x.getDirection(e,t.center),n.lastCalcEvent=n.futureCalcEvent||t,n.futureCalcEvent=t),t.velocityX=d.velocity.x,t.velocityY=d.velocity.y,t.interimAngle=d.angle,t.interimDirection=d.direction},extendEventData:function(t){var e=this.current,i=e.startEvent,s=e.lastEvent||i;(t.eventType==_||t.eventType==b)&&(i.touches=[],x.each(t.touches,function(t){i.touches.push({clientX:t.clientX,clientY:t.clientY})}));var o=t.timeStamp-i.timeStamp,n=t.center.clientX-i.center.clientX,r=t.center.clientY-i.center.clientY;return this.getCalculatedData(t,s.center,o,n,r),x.extend(t,{startEvent:i,deltaTime:o,deltaX:n,deltaY:r,distance:x.getDistance(i.center,t.center),angle:x.getAngle(i.center,t.center),direction:x.getDirection(i.center,t.center),scale:x.getScale(i.touches,t.touches),rotation:x.getRotation(i.touches,t.touches)}),t -},register:function(t){var e=t.defaults||{};return e[t.name]===n&&(e[t.name]=!0),x.extend(a.defaults,e,!0),t.index=t.index||1e3,this.gestures.push(t),this.gestures.sort(function(t,e){return t.indexe.index?1:0}),this.gestures}};a.Instance=function(t,e){var i=this;r(),this.element=t,this.enabled=!0,x.each(e,function(t,i){delete e[i],e[x.toCamelCase(i)]=t}),this.options=x.extend(x.extend({},a.defaults),e||{}),this.options.behavior&&x.toggleBehavior(this.element,this.options.behavior,!0),this.eventStartHandler=w.onTouch(t,g,function(t){i.enabled&&t.eventType==g?M.startDetect(i,t):t.eventType==_&&M.detect(t)}),this.eventHandlers=[]},a.Instance.prototype={on:function(t,e){var i=this;return w.on(i.element,t,e,function(t){i.eventHandlers.push({gesture:t,handler:e})}),i},off:function(t,e){var i=this;return w.off(i.element,t,e,function(t){var s=x.inArray({gesture:t,handler:e});s!==!1&&i.eventHandlers.splice(s,1)}),i},trigger:function(t,e){e||(e={});var i=a.DOCUMENT.createEvent("Event");i.initEvent(t,!0,!0),i.gesture=e;var s=this.element;return x.hasParent(e.target,s)&&(s=e.target),s.dispatchEvent(i),this},enable:function(t){return this.enabled=t,this},dispose:function(){var t,e;for(x.toggleBehavior(this.element,this.options.behavior,!1),t=-1;e=this.eventHandlers[++t];)x.off(this.element,e.gesture,e.handler);return this.eventHandlers=[],w.off(this.element,h[g],this.eventStartHandler),null}},function(t){function e(e,s){var o=M.current;if(!(s.options.dragMaxTouches>0&&e.touches.length>s.options.dragMaxTouches))switch(e.eventType){case g:i=!1;break;case v:if(e.distance0)){var r=Math.abs(s.options.dragMinDistance/e.distance);n.pageX+=e.deltaX*r,n.pageY+=e.deltaY*r,n.clientX+=e.deltaX*r,n.clientY+=e.deltaY*r,e=M.extendEventData(e)}(o.lastEvent.dragLockToAxis||s.options.dragLockToAxis&&s.options.dragLockMinDistance<=e.distance)&&(e.dragLockToAxis=!0);var a=o.lastEvent.direction;e.dragLockToAxis&&a!==e.direction&&(e.direction=x.isVertical(a)?e.deltaY<0?c:d:e.deltaX<0?l:p),i||(s.trigger(t+"start",e),i=!0),s.trigger(t,e),s.trigger(t+e.direction,e);var h=x.isVertical(e.direction);(s.options.dragBlockVertical&&h||s.options.dragBlockHorizontal&&!h)&&e.preventDefault();break;case b:i&&e.changedLength<=s.options.dragMaxTouches&&(s.trigger(t+"end",e),i=!1);break;case y:i=!1}}var i=!1;a.gestures.Drag={name:t,index:50,handler:e,defaults:{dragMinDistance:10,dragDistanceCorrection:!0,dragMaxTouches:1,dragBlockHorizontal:!1,dragBlockVertical:!1,dragLockToAxis:!1,dragLockMinDistance:25}}}("drag"),a.gestures.Gesture={name:"gesture",index:1337,handler:function(t,e){e.trigger(this.name,t)}},function(t){function e(e,s){var o=s.options,n=M.current;switch(e.eventType){case g:clearTimeout(i),n.name=t,i=setTimeout(function(){n&&n.name==t&&s.trigger(t,e)},o.holdTimeout);break;case v:e.distance>o.holdThreshold&&clearTimeout(i);break;case b:clearTimeout(i)}}var i;a.gestures.Hold={name:t,index:10,defaults:{holdTimeout:500,holdThreshold:2},handler:e}}("hold"),a.gestures.Release={name:"release",index:1/0,handler:function(t,e){t.eventType==b&&e.trigger(this.name,t)}},a.gestures.Swipe={name:"swipe",index:40,defaults:{swipeMinTouches:1,swipeMaxTouches:1,swipeVelocityX:.6,swipeVelocityY:.6},handler:function(t,e){if(t.eventType==b){var i=t.touches.length,s=e.options;if(is.swipeMaxTouches)return;(t.velocityX>s.swipeVelocityX||t.velocityY>s.swipeVelocityY)&&(e.trigger(this.name,t),e.trigger(this.name+t.direction,t))}}},function(t){function e(e,s){var o,n,r=s.options,a=M.current,h=M.previous;switch(e.eventType){case g:i=!1;break;case v:i=i||e.distance>r.tapMaxDistance;break;case y:!x.inStr(e.srcEvent.type,"cancel")&&e.deltaTimes.options.transformMinRotation&&s.trigger("rotate",e),o>s.options.transformMinScale&&(s.trigger("pinch",e),s.trigger("pinch"+(e.scale<1?"in":"out"),e));break;case b:i&&e.changedLength<2&&(s.trigger(t+"end",e),i=!1)}}var i=!1;a.gestures.Transform={name:t,index:45,defaults:{transformMinScale:.01,transformMinRotation:1},handler:e}}("transform"),s=function(){return a}.call(e,i,e,t),!(s!==n&&(t.exports=s))}(window)},function(t,e){var i,s,o;!function(n,r){s=[],i=r,o="function"==typeof i?i.apply(e,s):i,!(void 0!==o&&(t.exports=o))}(this,function(){function t(t){var e,i=t&&t.preventDefault||!1,s=t&&t.container||window,o={},n={keydown:{},keyup:{}},r={};for(e=97;122>=e;e++)r[String.fromCharCode(e)]={code:65+(e-97),shift:!1};for(e=65;90>=e;e++)r[String.fromCharCode(e)]={code:e,shift:!0};for(e=0;9>=e;e++)r[""+e]={code:48+e,shift:!1};for(e=1;12>=e;e++)r["F"+e]={code:111+e,shift:!1};for(e=0;9>=e;e++)r["num"+e]={code:96+e,shift:!1};r["num*"]={code:106,shift:!1},r["num+"]={code:107,shift:!1},r["num-"]={code:109,shift:!1},r["num/"]={code:111,shift:!1},r["num."]={code:110,shift:!1},r.left={code:37,shift:!1},r.up={code:38,shift:!1},r.right={code:39,shift:!1},r.down={code:40,shift:!1},r.space={code:32,shift:!1},r.enter={code:13,shift:!1},r.shift={code:16,shift:void 0},r.esc={code:27,shift:!1},r.backspace={code:8,shift:!1},r.tab={code:9,shift:!1},r.ctrl={code:17,shift:!1},r.alt={code:18,shift:!1},r["delete"]={code:46,shift:!1},r.pageup={code:33,shift:!1},r.pagedown={code:34,shift:!1},r["="]={code:187,shift:!1},r["-"]={code:189,shift:!1},r["]"]={code:221,shift:!1},r["["]={code:219,shift:!1};var a=function(t){d(t,"keydown")},h=function(t){d(t,"keyup")},d=function(t,e){if(void 0!==n[e][t.keyCode]){for(var s=n[e][t.keyCode],o=0;oe-n?(i=t.clone().add(o-1,"months"),s=(e-n)/(n-i)):(i=t.clone().add(o+1,"months"),s=(e-n)/(i-n)),-(o+s)}function f(t,e,i){var s;return null==i?e:null!=t.meridiemHour?t.meridiemHour(e,i):null!=t.isPM?(s=t.isPM(i),s&&12>e&&(e+=12),s||12!==e||(e=0),e):e}function g(){}function v(t,e){e!==!1&&R(t),_(this,t),this._d=new Date(+t._d),Di===!1&&(Di=!0,Ce.updateOffset(this),Di=!1)}function y(t){var e=N(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._locale=Ce.localeData(),this._bubble()}function b(t,e){for(var i in e)a(e,i)&&(t[i]=e[i]);return a(e,"toString")&&(t.toString=e.toString),a(e,"valueOf")&&(t.valueOf=e.valueOf),t}function _(t,e){var i,s,o;if("undefined"!=typeof e._isAMomentObject&&(t._isAMomentObject=e._isAMomentObject),"undefined"!=typeof e._i&&(t._i=e._i),"undefined"!=typeof e._f&&(t._f=e._f),"undefined"!=typeof e._l&&(t._l=e._l),"undefined"!=typeof e._strict&&(t._strict=e._strict),"undefined"!=typeof e._tzm&&(t._tzm=e._tzm),"undefined"!=typeof e._isUTC&&(t._isUTC=e._isUTC),"undefined"!=typeof e._offset&&(t._offset=e._offset),"undefined"!=typeof e._pf&&(t._pf=e._pf),"undefined"!=typeof e._locale&&(t._locale=e._locale),Ye.length>0)for(i in Ye)s=Ye[i],o=e[s],"undefined"!=typeof o&&(t[s]=o);return t}function x(t){return 0>t?Math.ceil(t):Math.floor(t)}function w(t,e,i){for(var s=""+Math.abs(t),o=t>=0;s.lengths;s++)(i&&t[s]!==e[s]||!i&&L(t[s])!==L(e[s]))&&r++;return r+n}function k(t){if(t){var e=t.toLowerCase().replace(/(.)s$/,"$1");t=gi[t]||vi[e]||e}return t}function N(t){var e,i,s={};for(i in t)a(t,i)&&(e=k(i),e&&(s[e]=t[i]));return s}function I(t){var e,i;if(0===t.indexOf("week"))e=7,i="day";else{if(0!==t.indexOf("month"))return;e=12,i="month"}Ce[t]=function(s,o){var r,a,h=Ce._locale[t],d=[];if("number"==typeof s&&(o=s,s=n),a=function(t){var e=Ce().utc().set(i,t);return h.call(Ce._locale,e,s||"")},null!=o)return a(o);for(r=0;e>r;r++)d.push(a(r));return d}}function L(t){var e=+t,i=0;return 0!==e&&isFinite(e)&&(i=e>=0?Math.floor(e):Math.ceil(e)),i}function z(t,e){return new Date(Date.UTC(t,e+1,0)).getUTCDate()}function A(t,e,i){return me(Ce([t,11,31+e-i]),e,i).week}function P(t){return F(t)?366:365}function F(t){return t%4===0&&t%100!==0||t%400===0}function R(t){var e;t._a&&-2===t._pf.overflow&&(e=t._a[ze]<0||t._a[ze]>11?ze:t._a[Ae]<1||t._a[Ae]>z(t._a[Le],t._a[ze])?Ae:t._a[Pe]<0||t._a[Pe]>24||24===t._a[Pe]&&(0!==t._a[Fe]||0!==t._a[Re]||0!==t._a[Be])?Pe:t._a[Fe]<0||t._a[Fe]>59?Fe:t._a[Re]<0||t._a[Re]>59?Re:t._a[Be]<0||t._a[Be]>999?Be:-1,t._pf._overflowDayOfYear&&(Le>e||e>Ae)&&(e=Ae),t._pf.overflow=e)}function B(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._pf.bigHour===n)),t._isValid}function H(t){return t?t.toLowerCase().replace("_","-"):t}function Y(t){for(var e,i,s,o,n=0;n0;){if(s=W(o.slice(0,e).join("-")))return s;if(i&&i.length>=e&&E(o,i,!0)>=e-1)break;e--}n++}return null}function W(t){var e=null;if(!He[t]&&We)try{e=Ce.locale(),!function(){var t=new Error('Cannot find module "./locale"');throw t.code="MODULE_NOT_FOUND",t}(),Ce.locale(e)}catch(i){}return He[t]}function G(t,e){var i,s;return e._isUTC?(i=e.clone(),s=(Ce.isMoment(t)||O(t)?+t:+Ce(t))-+i,i._d.setTime(+i._d+s),Ce.updateOffset(i,!1),i):Ce(t).local()}function j(t){return t.match(/\[[\s\S]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"")}function V(t){var e,i,s=t.match(Ue);for(e=0,i=s.length;i>e;e++)s[e]=wi[s[e]]?wi[s[e]]:j(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 U(t,e){return t.isValid()?(e=X(e,t.localeData()),yi[e]||(yi[e]=V(e)),yi[e](t)):t.localeData().invalidDate()}function X(t,e){function i(t){return e.longDateFormat(t)||t}var s=5;for(Xe.lastIndex=0;s>=0&&Xe.test(t);)t=t.replace(Xe,i),Xe.lastIndex=0,s-=1;return t}function q(t,e){var i,s=e._strict;switch(t){case"Q":return oi;case"DDDD":return ri;case"YYYY":case"GGGG":case"gggg":return s?ai:Qe;case"Y":case"G":case"g":return di;case"YYYYYY":case"YYYYY":case"GGGGG":case"ggggg":return s?hi:Ke;case"S":if(s)return oi;case"SS":if(s)return ni;case"SSS":if(s)return ri;case"DDD":return Ze;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":return Je;case"a":case"A":return e._locale._meridiemParse;case"x":return ii;case"X":return si;case"Z":case"ZZ":return ti;case"T":return ei;case"SSSS":return $e;case"MM":case"DD":case"YY":case"GG":case"gg":case"HH":case"hh":case"mm":case"ss":case"ww":case"WW":return s?ni:qe;case"M":case"D":case"d":case"H":case"h":case"m":case"s":case"w":case"W":case"e":case"E":return qe;case"Do":return s?e._locale._ordinalParse:e._locale._ordinalParseLenient;default:return i=new RegExp(se(ie(t.replace("\\","")),"i"))}}function Z(t){t=t||"";var e=t.match(ti)||[],i=e[e.length-1]||[],s=(i+"").match(mi)||["-",0,0],o=+(60*s[1])+L(s[2]);return"+"===s[0]?o:-o}function Q(t,e,i){var s,o=i._a;switch(t){case"Q":null!=e&&(o[ze]=3*(L(e)-1));break;case"M":case"MM":null!=e&&(o[ze]=L(e)-1);break;case"MMM":case"MMMM":s=i._locale.monthsParse(e,t,i._strict),null!=s?o[ze]=s:i._pf.invalidMonth=e;break;case"D":case"DD":null!=e&&(o[Ae]=L(e));break;case"Do":null!=e&&(o[Ae]=L(parseInt(e.match(/\d{1,2}/)[0],10)));break;case"DDD":case"DDDD":null!=e&&(i._dayOfYear=L(e));break;case"YY":o[Le]=Ce.parseTwoDigitYear(e);break;case"YYYY":case"YYYYY":case"YYYYYY":o[Le]=L(e);break;case"a":case"A":i._meridiem=e;break;case"h":case"hh":i._pf.bigHour=!0;case"H":case"HH":o[Pe]=L(e);break;case"m":case"mm":o[Fe]=L(e);break;case"s":case"ss":o[Re]=L(e);break;case"S":case"SS":case"SSS":case"SSSS":o[Be]=L(1e3*("0."+e));break;case"x":i._d=new Date(L(e));break;case"X":i._d=new Date(1e3*parseFloat(e));break;case"Z":case"ZZ":i._useUTC=!0,i._tzm=Z(e);break;case"dd":case"ddd":case"dddd":s=i._locale.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]=L(e));break;case"gg":case"GG":i._w=i._w||{},i._w[t]=Ce.parseTwoDigitYear(e)}}function K(t){var e,i,s,o,n,a,h;e=t._w,null!=e.GG||null!=e.W||null!=e.E?(n=1,a=4,i=r(e.GG,t._a[Le],me(Ce(),1,4).year),s=r(e.W,1),o=r(e.E,1)):(n=t._locale._week.dow,a=t._locale._week.doy,i=r(e.gg,t._a[Le],me(Ce(),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=fe(i,s,o,a,n),t._a[Le]=h.year,t._dayOfYear=h.dayOfYear}function $(t){var e,i,s,o,n=[];if(!t._d){for(s=te(t),t._w&&null==t._a[Ae]&&null==t._a[ze]&&K(t),t._dayOfYear&&(o=r(t._a[Le],s[Le]),t._dayOfYear>P(o)&&(t._pf._overflowDayOfYear=!0),i=le(o,0,t._dayOfYear),t._a[ze]=i.getUTCMonth(),t._a[Ae]=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];24===t._a[Pe]&&0===t._a[Fe]&&0===t._a[Re]&&0===t._a[Be]&&(t._nextDay=!0,t._a[Pe]=0),t._d=(t._useUTC?le:de).apply(null,n),null!=t._tzm&&t._d.setUTCMinutes(t._d.getUTCMinutes()-t._tzm),t._nextDay&&(t._a[Pe]=24)}}function J(t){var e;t._d||(e=N(t._i),t._a=[e.year,e.month,e.day||e.date,e.hour,e.minute,e.second,e.millisecond],$(t))}function te(t){var e=new Date;return t._useUTC?[e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()]:[e.getFullYear(),e.getMonth(),e.getDate()]}function ee(t){if(t._f===Ce.ISO_8601)return void ne(t);t._a=[],t._pf.empty=!0;var e,i,s,o,r,a=""+t._i,h=a.length,d=0;for(s=X(t._f,t._locale).match(Ue)||[],e=0;e0&&t._pf.unusedInput.push(r),a=a.slice(a.indexOf(i)+i.length),d+=i.length),wi[o]?(i?t._pf.empty=!1:t._pf.unusedTokens.push(o),Q(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._pf.bigHour===!0&&t._a[Pe]<=12&&(t._pf.bigHour=n),t._a[Pe]=f(t._locale,t._a[Pe],t._meridiem),$(t),R(t)}function ie(t){return t.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(t,e,i,s,o){return e||i||s||o})}function se(t){return t.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function oe(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));b(t,i||e)}function ne(t){var e,i,s=t._i,o=li.exec(s);if(o){for(t._pf.iso=!0,e=0,i=pi.length;i>e;e++)if(pi[e][1].exec(s)){t._f=pi[e][0]+(o[6]||" ");break}for(e=0,i=ui.length;i>e;e++)if(ui[e][1].exec(s)){t._f+=ui[e][0];break}s.match(ti)&&(t._f+="Z"),ee(t)}else t._isValid=!1}function re(t){ne(t),t._isValid===!1&&(delete t._isValid,Ce.createFromInputFallback(t))}function ae(t,e){var i,s=[];for(i=0;it&&a.setFullYear(t),a}function le(t){var e=new Date(Date.UTC.apply(null,arguments));return 1970>t&&e.setUTCFullYear(t),e}function ce(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 pe(t,e,i,s,o){return o.relativeTime(e||1,!!i,t,s)}function ue(t,e,i){var s=Ce.duration(t).abs(),o=Ne(s.as("s")),n=Ne(s.as("m")),r=Ne(s.as("h")),a=Ne(s.as("d")),h=Ne(s.as("M")),d=Ne(s.as("y")),l=o0,l[4]=i,pe.apply({},l)}function me(t,e,i){var s,o=i-e,n=i-t.day();return n>o&&(n-=7),o-7>n&&(n+=7),s=Ce(t).add(n,"d"),{week:Math.ceil(s.dayOfYear()/7),year:s.year()}}function fe(t,e,i,s,o){var n,r,a=le(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:P(t-1)+r}}function ge(t){var e,i=t._i,s=t._f;return t._locale=t._locale||Ce.localeData(t._l),null===i||s===n&&""===i?Ce.invalid({nullInput:!0}):("string"==typeof i&&(t._i=i=t._locale.preparse(i)),Ce.isMoment(i)?new v(i,!0):(s?T(s)?oe(t):ee(t):he(t),e=new v(t),e._nextDay&&(e.add(1,"d"),e._nextDay=n),e))}function ve(t,e){var i,s;if(1===e.length&&T(e[0])&&(e=e[0]),!e.length)return Ce();for(i=e[0],s=1;s=0?"+":"-";return e+w(Math.abs(t),6)},gg:function(){return w(this.weekYear()%100,2)},gggg:function(){return w(this.weekYear(),4)},ggggg:function(){return w(this.weekYear(),5)},GG:function(){return w(this.isoWeekYear()%100,2)},GGGG:function(){return w(this.isoWeekYear(),4)},GGGGG:function(){return w(this.isoWeekYear(),5)},e:function(){return this.weekday()},E:function(){return this.isoWeekday()},a:function(){return this.localeData().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.localeData().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 L(this.milliseconds()/100)},SS:function(){return w(L(this.milliseconds()/10),2)},SSS:function(){return w(this.milliseconds(),3)},SSSS:function(){return w(this.milliseconds(),3)},Z:function(){var t=this.utcOffset(),e="+";return 0>t&&(t=-t,e="-"),e+w(L(t/60),2)+":"+w(L(t)%60,2)},ZZ:function(){var t=this.utcOffset(),e="+";return 0>t&&(t=-t,e="-"),e+w(L(t/60),2)+w(L(t)%60,2)},z:function(){return this.zoneAbbr()},zz:function(){return this.zoneName()},x:function(){return this.valueOf()},X:function(){return this.unix()},Q:function(){return this.quarter()}},Si={},Mi=["months","monthsShort","weekdays","weekdaysShort","weekdaysMin"],Di=!1;_i.length;)Oe=_i.pop(),wi[Oe+"o"]=u(wi[Oe],Oe);for(;xi.length;)Oe=xi.pop(),wi[Oe+Oe]=p(wi[Oe],2);wi.DDDD=p(wi.DDD,3),b(g.prototype,{set:function(t){var e,i;for(i in t)e=t[i],"function"==typeof e?this[i]=e:this["_"+i]=e;this._ordinalParseLenient=new RegExp(this._ordinalParse.source+"|"+/\d{1,2}/.source)},_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,e,i){var s,o,n;for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),s=0;12>s;s++){if(o=Ce.utc([2e3,s]),i&&!this._longMonthsParse[s]&&(this._longMonthsParse[s]=new RegExp("^"+this.months(o,"").replace(".","")+"$","i"),this._shortMonthsParse[s]=new RegExp("^"+this.monthsShort(o,"").replace(".","")+"$","i")),i||this._monthsParse[s]||(n="^"+this.months(o,"")+"|^"+this.monthsShort(o,""),this._monthsParse[s]=new RegExp(n.replace(".",""),"i")),i&&"MMMM"===e&&this._longMonthsParse[s].test(t))return s;if(i&&"MMM"===e&&this._shortMonthsParse[s].test(t))return s;if(!i&&this._monthsParse[s].test(t))return s}},_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=Ce([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:{LTS:"h:mm:ss A",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,i){var s=this._calendar[t];return"function"==typeof s?s.apply(e,[i]):s},_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",_ordinalParse:/\d{1,2}/,preparse:function(t){return t},postformat:function(t){return t},week:function(t){return me(t,this._week.dow,this._week.doy).week},_week:{dow:0,doy:6},firstDayOfWeek:function(){return this._week.dow},firstDayOfYear:function(){return this._week.doy},_invalidDate:"Invalid date",invalidDate:function(){return this._invalidDate}}),Ce=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=h(),ge(o)},Ce.suppressDeprecationWarnings=!1,Ce.createFromInputFallback=l("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+(t._useUTC?" UTC":""))}),Ce.min=function(){var t=[].slice.call(arguments,0);return ve("isBefore",t)},Ce.max=function(){var t=[].slice.call(arguments,0);return ve("isAfter",t)},Ce.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=h(),ge(o).utc()},Ce.unix=function(t){return Ce(1e3*t)},Ce.duration=function(t,e){var i,s,o,n,r=t,h=null;return Ce.isDuration(t)?r={ms:t._milliseconds,d:t._days,M:t._months}:"number"==typeof t?(r={},e?r[e]=t:r.milliseconds=t):(h=je.exec(t))?(i="-"===h[1]?-1:1,r={y:0,d:L(h[Ae])*i,h:L(h[Pe])*i,m:L(h[Fe])*i,s:L(h[Re])*i,ms:L(h[Be])*i}):(h=Ve.exec(t))?(i="-"===h[1]?-1:1,o=function(t){var e=t&&parseFloat(t.replace(",","."));return(isNaN(e)?0:e)*i},r={y:o(h[2]),M:o(h[3]),d:o(h[4]),h:o(h[5]),m:o(h[6]),s:o(h[7]),w:o(h[8])}):null==r?r={}:"object"==typeof r&&("from"in r||"to"in r)&&(n=M(Ce(r.from),Ce(r.to)),r={},r.ms=n.milliseconds,r.M=n.months),s=new y(r),Ce.isDuration(t)&&a(t,"_locale")&&(s._locale=t._locale),s},Ce.version=Ee,Ce.defaultFormat=ci,Ce.ISO_8601=function(){},Ce.momentProperties=Ye,Ce.updateOffset=function(){},Ce.relativeTimeThreshold=function(t,e){return bi[t]===n?!1:e===n?bi[t]:(bi[t]=e,!0)},Ce.lang=l("moment.lang is deprecated. Use moment.locale instead.",function(t,e){return Ce.locale(t,e)}),Ce.locale=function(t,e){var i;return t&&(i="undefined"!=typeof e?Ce.defineLocale(t,e):Ce.localeData(t),i&&(Ce.duration._locale=Ce._locale=i)),Ce._locale._abbr},Ce.defineLocale=function(t,e){return null!==e?(e.abbr=t,He[t]||(He[t]=new g),He[t].set(e),Ce.locale(t),He[t]):(delete He[t],null)},Ce.langData=l("moment.langData is deprecated. Use moment.localeData instead.",function(t){return Ce.localeData(t)}),Ce.localeData=function(t){var e;if(t&&t._locale&&t._locale._abbr&&(t=t._locale._abbr),!t)return Ce._locale;if(!T(t)){if(e=W(t))return e;t=[t]}return Y(t)},Ce.isMoment=function(t){return t instanceof v||null!=t&&a(t,"_isAMomentObject")},Ce.isDuration=function(t){return t instanceof y};for(Oe=Mi.length-1;Oe>=0;--Oe)I(Mi[Oe]);Ce.normalizeUnits=function(t){return k(t)},Ce.invalid=function(t){var e=Ce.utc(0/0);return null!=t?b(e._pf,t):e._pf.userInvalidated=!0,e},Ce.parseZone=function(){return Ce.apply(null,arguments).parseZone()},Ce.parseTwoDigitYear=function(t){return L(t)+(L(t)>68?1900:2e3)},Ce.isDate=O,b(Ce.fn=v.prototype,{clone:function(){return Ce(this) -},valueOf:function(){return+this._d-6e4*(this._offset||0)},unix:function(){return Math.floor(+this/1e3)},toString:function(){return this.clone().locale("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=Ce(this).utc();return 00:!1},parsingFlags:function(){return b({},this._pf)},invalidAt:function(){return this._pf.overflow},utc:function(t){return this.utcOffset(0,t)},local:function(t){return this._isUTC&&(this.utcOffset(0,t),this._isUTC=!1,t&&this.subtract(this._dateUtcOffset(),"m")),this},format:function(t){var e=U(this,t||Ce.defaultFormat);return this.localeData().postformat(e)},add:D(1,"add"),subtract:D(-1,"subtract"),diff:function(t,e,i){var s,o,n=G(t,this),r=6e4*(n.utcOffset()-this.utcOffset());return e=k(e),"year"===e||"month"===e||"quarter"===e?(o=m(this,n),"quarter"===e?o/=3:"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:x(o)},from:function(t,e){return Ce.duration({to:this,from:t}).locale(this.locale()).humanize(!e)},fromNow:function(t){return this.from(Ce(),t)},calendar:function(t){var e=t||Ce(),i=G(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.localeData().calendar(o,this,Ce(e)))},isLeapYear:function(){return F(this.year())},isDST:function(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},day:function(t){var e=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=t?(t=ce(t,this.localeData()),this.add(t-e,"d")):e},month:xe("Month",!0),startOf:function(t){switch(t=k(t)){case"year":this.month(0);case"quarter":case"month":this.date(1);case"week":case"isoWeek":case"day":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return"week"===t?this.weekday(0):"isoWeek"===t&&this.isoWeekday(1),"quarter"===t&&this.month(3*Math.floor(this.month()/3)),this},endOf:function(t){return t=k(t),t===n||"millisecond"===t?this:this.startOf(t).add(1,"isoWeek"===t?"week":t).subtract(1,"ms")},isAfter:function(t,e){var i;return e=k("undefined"!=typeof e?e:"millisecond"),"millisecond"===e?(t=Ce.isMoment(t)?t:Ce(t),+this>+t):(i=Ce.isMoment(t)?+t:+Ce(t),i<+this.clone().startOf(e))},isBefore:function(t,e){var i;return e=k("undefined"!=typeof e?e:"millisecond"),"millisecond"===e?(t=Ce.isMoment(t)?t:Ce(t),+t>+this):(i=Ce.isMoment(t)?+t:+Ce(t),+this.clone().endOf(e)t?this:t}),max:l("moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548",function(t){return t=Ce.apply(null,arguments),t>this?this:t}),zone:l("moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779",function(t,e){return null!=t?("string"!=typeof t&&(t=-t),this.utcOffset(t,e),this):-this.utcOffset()}),utcOffset:function(t,e){var i,s=this._offset||0;return null!=t?("string"==typeof t&&(t=Z(t)),Math.abs(t)<16&&(t=60*t),!this._isUTC&&e&&(i=this._dateUtcOffset()),this._offset=t,this._isUTC=!0,null!=i&&this.add(i,"m"),s!==t&&(!e||this._changeInProgress?C(this,Ce.duration(t-s,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,Ce.updateOffset(this,!0),this._changeInProgress=null)),this):this._isUTC?s:this._dateUtcOffset()},isLocal:function(){return!this._isUTC},isUtcOffset:function(){return this._isUTC},isUtc:function(){return this._isUTC&&0===this._offset},zoneAbbr:function(){return this._isUTC?"UTC":""},zoneName:function(){return this._isUTC?"Coordinated Universal Time":""},parseZone:function(){return this._tzm?this.utcOffset(this._tzm):"string"==typeof this._i&&this.utcOffset(Z(this._i)),this},hasAlignedHourOffset:function(t){return t=t?Ce(t).utcOffset():0,(this.utcOffset()-t)%60===0},daysInMonth:function(){return z(this.year(),this.month())},dayOfYear:function(t){var e=Ne((Ce(this).startOf("day")-Ce(this).startOf("year"))/864e5)+1;return null==t?e:this.add(t-e,"d")},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=me(this,this.localeData()._week.dow,this.localeData()._week.doy).year;return null==t?e:this.add(t-e,"y")},isoWeekYear:function(t){var e=me(this,1,4).year;return null==t?e:this.add(t-e,"y")},week:function(t){var e=this.localeData().week(this);return null==t?e:this.add(7*(t-e),"d")},isoWeek:function(t){var e=me(this,1,4).week;return null==t?e:this.add(7*(t-e),"d")},weekday:function(t){var e=(this.day()+7-this.localeData()._week.dow)%7;return null==t?e:this.add(t-e,"d")},isoWeekday:function(t){return null==t?this.day()||7:this.day(this.day()%7?t:t-7)},isoWeeksInYear:function(){return A(this.year(),1,4)},weeksInYear:function(){var t=this.localeData()._week;return A(this.year(),t.dow,t.doy)},get:function(t){return t=k(t),this[t]()},set:function(t,e){var i;if("object"==typeof t)for(i in t)this.set(i,t[i]);else t=k(t),"function"==typeof this[t]&&this[t](e);return this},locale:function(t){var e;return t===n?this._locale._abbr:(e=Ce.localeData(t),null!=e&&(this._locale=e),this)},lang:l("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(t){return t===n?this.localeData():this.locale(t)}),localeData:function(){return this._locale},_dateUtcOffset:function(){return 15*-Math.round(this._d.getTimezoneOffset()/15)}}),Ce.fn.millisecond=Ce.fn.milliseconds=xe("Milliseconds",!1),Ce.fn.second=Ce.fn.seconds=xe("Seconds",!1),Ce.fn.minute=Ce.fn.minutes=xe("Minutes",!1),Ce.fn.hour=Ce.fn.hours=xe("Hours",!0),Ce.fn.date=xe("Date",!0),Ce.fn.dates=l("dates accessor is deprecated. Use date instead.",xe("Date",!0)),Ce.fn.year=xe("FullYear",!0),Ce.fn.years=l("years accessor is deprecated. Use year instead.",xe("FullYear",!0)),Ce.fn.days=Ce.fn.day,Ce.fn.months=Ce.fn.month,Ce.fn.weeks=Ce.fn.week,Ce.fn.isoWeeks=Ce.fn.isoWeek,Ce.fn.quarters=Ce.fn.quarter,Ce.fn.toJSON=Ce.fn.toISOString,Ce.fn.isUTC=Ce.fn.isUtc,b(Ce.duration.fn=y.prototype,{_bubble:function(){var t,e,i,s=this._milliseconds,o=this._days,n=this._months,r=this._data,a=0;r.milliseconds=s%1e3,t=x(s/1e3),r.seconds=t%60,e=x(t/60),r.minutes=e%60,i=x(e/60),r.hours=i%24,o+=x(i/24),a=x(we(o)),o-=x(Se(a)),n+=x(o/30),o%=30,a+=x(n/12),n%=12,r.days=o,r.months=n,r.years=a},abs:function(){return this._milliseconds=Math.abs(this._milliseconds),this._days=Math.abs(this._days),this._months=Math.abs(this._months),this._data.milliseconds=Math.abs(this._data.milliseconds),this._data.seconds=Math.abs(this._data.seconds),this._data.minutes=Math.abs(this._data.minutes),this._data.hours=Math.abs(this._data.hours),this._data.months=Math.abs(this._data.months),this._data.years=Math.abs(this._data.years),this},weeks:function(){return x(this.days()/7)},valueOf:function(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*L(this._months/12)},humanize:function(t){var e=ue(this,!t,this.localeData());return t&&(e=this.localeData().pastFuture(+this,e)),this.localeData().postformat(e)},add:function(t,e){var i=Ce.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=Ce.duration(t,e);return this._milliseconds-=i._milliseconds,this._days-=i._days,this._months-=i._months,this._bubble(),this},get:function(t){return t=k(t),this[t.toLowerCase()+"s"]()},as:function(t){var e,i;if(t=k(t),"month"===t||"year"===t)return e=this._days+this._milliseconds/864e5,i=this._months+12*we(e),"month"===t?i:i/12;switch(e=this._days+Math.round(Se(this._months/12)),t){case"week":return e/7+this._milliseconds/6048e5;case"day":return e+this._milliseconds/864e5;case"hour":return 24*e+this._milliseconds/36e5;case"minute":return 24*e*60+this._milliseconds/6e4;case"second":return 24*e*60*60+this._milliseconds/1e3;case"millisecond":return Math.floor(24*e*60*60*1e3)+this._milliseconds;default:throw new Error("Unknown unit "+t)}},lang:Ce.fn.lang,locale:Ce.fn.locale,toIsoString:l("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",function(){return this.toISOString()}),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"},localeData:function(){return this._locale},toJSON:function(){return this.toISOString()}}),Ce.duration.fn.toString=Ce.duration.fn.toISOString;for(Oe in fi)a(fi,Oe)&&Me(Oe.toLowerCase());Ce.duration.fn.asMilliseconds=function(){return this.as("ms")},Ce.duration.fn.asSeconds=function(){return this.as("s")},Ce.duration.fn.asMinutes=function(){return this.as("m")},Ce.duration.fn.asHours=function(){return this.as("h")},Ce.duration.fn.asDays=function(){return this.as("d")},Ce.duration.fn.asWeeks=function(){return this.as("weeks")},Ce.duration.fn.asMonths=function(){return this.as("M")},Ce.duration.fn.asYears=function(){return this.as("y")},Ce.locale("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(t){var e=t%10,i=1===L(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th";return t+i}}),We?o.exports=Ce:(s=function(t,e,i){return i.config&&i.config()&&i.config().noGlobal===!0&&(ke.moment=Te),Ce}.call(e,i,e,o),!(s!==n&&(o.exports=s)),De(!0))}).call(this)}).call(e,function(){return this}(),i(71)(t))},function(t,e){e.startWithClustering=function(){this.clusterToFit(this.constants.clustering.initialMaxNodes,!0),this.updateLabels(),1==this.constants.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(),this.forceAggregateHubs(!0),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._updateCalculationNodes(),this.updateLabels();this.moving!=e&&this.start()},e.updateClustersDefault=function(){1==this.constants.clustering.enabled&&1==this.constants.clustering.clusterByZoom&&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,r=this.previousScalethis.scale&&0==t;1==a&&this._collapseSector(),1==a||-1==t?this._formClusters(i):(1==r||1==t)&&(1==i?this._openClusters(e,i):this._openClusters(e,!1)),this._updateNodeIndexList(),this.nodeIndices.length!=n||1!=a&&-1!=t||(this._aggregateHubs(i),this._updateNodeIndexList()),(1==a||-1==t)&&(this.handleChains(),this._updateNodeIndexList()),this.previousScale=this.scale,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.updateLabels(),this._updateCalculationNodes(),this.nodeIndices.length!=i&&(this.clusterSession+=1),(0==t||void 0===t)&&this.moving!=e&&this.start()},e._openClustersBySize=function(){if(1==this.constants.clustering.clusterByZoom)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&&(void 0===s&&(s=!1),e=s||e,t.formationScalei)){var r=n.from,a=n.to;n.to.options.mass>n.from.options.mass&&(r=n.to,a=n.from),1==a.dynamicEdges.length?this._addToCluster(r,a,!1):1==r.dynamicEdges.length&&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.dynamicEdges.length){var i=e.dynamicEdges[0],s=i.toId==e.id?this.nodes[i.fromId]:this.nodes[i.toId];e.id!=s.id&&(s.options.mass>e.options.mass?this._addToCluster(s,e,!0):this._addToCluster(e,s,!0))}}},e._clusterToSmallestNeighbour=function(t){for(var e=-1,i=null,s=0;so.clusterSessions.length&&(e=o.clusterSessions.length,i=o)}null!=o&&void 0!==this.nodes[o.id]&&this._addToCluster(o,t,!0)},e._formClustersByHub=function(t,e){for(var i in this.nodes)this.nodes.hasOwnProperty(i)&&this._formClusterFromHub(this.nodes[i],t,e)},e._formClusterFromHub=function(t,e,i,s){if(void 0===s&&(s=0),t.dynamicEdges.length>=this.hubThreshold&&0==i||t.dynamicEdges.length==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){var u=[],m={};for(c=0;l>c;c++){p=this.edges[d[c]];var f=this.nodes[p.fromId==t.id?p.toId:p.fromId];void 0===m[f.id]&&(m[f.id]=!0,u.push(f))}for(c=0;c1&&(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.dynamicEdges.length),t+=n.dynamicEdges.length,e+=Math.pow(n.dynamicEdges.length,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].dynamicEdges.length&&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].dynamicEdges.length&&(t+=1),e+=1);return t/e}},function(t,e,i){var s=i(1),o=i(40);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 o({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](o[0],o[1]):this[t](e))}return this._loadLatestSector(),i},e._doInSupportSector=function(t,e){var i=!1;if(void 0===e)this._switchToSupportSector(),i=this[t]();else{this._switchToSupportSector();var s=Array.prototype.splice.call(arguments,1);i=s.length>1?this[t](s[0],s[1]):this[t](e)}return this._loadLatestSector(),i},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;ei;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,!0)}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,!1,!0)}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(40),n=i(37);e._clearManipulatorBar=function(){this._recursiveDOMDelete(this.manipulationDiv),this.manipulationDOM={},this._manipulationReleaseOverload=function(){},delete this.sectors.support.nodes.targetNode,delete this.sectors.support.nodes.targetViaNode,this.controlNodesActive=!1,this.freezeSimulationEnabled=!1},e._restoreOverloadedFunctions=function(){for(var t in this.cachedFunctions)this.cachedFunctions.hasOwnProperty(t)&&(this[t]=this.cachedFunctions[t],delete this.cachedFunctions[t])},e._toggleEditMode=function(){this.editMode=!this.editMode;var t=this.manipulationDiv,e=this.closeDiv,i=this.editModeDiv;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(){this.boundFunction&&this.off("select",this.boundFunction);var t=this.constants.locales[this.constants.locale];if(void 0!==this.edgeBeingEdited&&(this.edgeBeingEdited._disableControlNodes(),this.edgeBeingEdited=void 0,this.selectedControlNode=null,this.controlNodesActive=!1,this._redraw()),this._restoreOverloadedFunctions(),this.freezeSimulationEnabled=!1,this.blockConnectingEdgeSelection=!1,this.forceAppendSelection=!1,this.manipulationDOM={},1==this.editMode){for(;this.manipulationDiv.hasChildNodes();)this.manipulationDiv.removeChild(this.manipulationDiv.firstChild);this.manipulationDOM.addNodeSpan=document.createElement("span"),this.manipulationDOM.addNodeSpan.className="network-manipulationUI add",this.manipulationDOM.addNodeLabelSpan=document.createElement("span"),this.manipulationDOM.addNodeLabelSpan.className="network-manipulationLabel",this.manipulationDOM.addNodeLabelSpan.innerHTML=t.addNode,this.manipulationDOM.addNodeSpan.appendChild(this.manipulationDOM.addNodeLabelSpan),this.manipulationDOM.seperatorLineDiv1=document.createElement("div"),this.manipulationDOM.seperatorLineDiv1.className="network-seperatorLine",this.manipulationDOM.addEdgeSpan=document.createElement("span"),this.manipulationDOM.addEdgeSpan.className="network-manipulationUI connect",this.manipulationDOM.addEdgeLabelSpan=document.createElement("span"),this.manipulationDOM.addEdgeLabelSpan.className="network-manipulationLabel",this.manipulationDOM.addEdgeLabelSpan.innerHTML=t.addEdge,this.manipulationDOM.addEdgeSpan.appendChild(this.manipulationDOM.addEdgeLabelSpan),this.manipulationDiv.appendChild(this.manipulationDOM.addNodeSpan),this.manipulationDiv.appendChild(this.manipulationDOM.seperatorLineDiv1),this.manipulationDiv.appendChild(this.manipulationDOM.addEdgeSpan),1==this._getSelectedNodeCount()&&this.triggerFunctions.edit?(this.manipulationDOM.seperatorLineDiv2=document.createElement("div"),this.manipulationDOM.seperatorLineDiv2.className="network-seperatorLine",this.manipulationDOM.editNodeSpan=document.createElement("span"),this.manipulationDOM.editNodeSpan.className="network-manipulationUI edit",this.manipulationDOM.editNodeLabelSpan=document.createElement("span"),this.manipulationDOM.editNodeLabelSpan.className="network-manipulationLabel",this.manipulationDOM.editNodeLabelSpan.innerHTML=t.editNode,this.manipulationDOM.editNodeSpan.appendChild(this.manipulationDOM.editNodeLabelSpan),this.manipulationDiv.appendChild(this.manipulationDOM.seperatorLineDiv2),this.manipulationDiv.appendChild(this.manipulationDOM.editNodeSpan)):1==this._getSelectedEdgeCount()&&0==this._getSelectedNodeCount()&&(this.manipulationDOM.seperatorLineDiv3=document.createElement("div"),this.manipulationDOM.seperatorLineDiv3.className="network-seperatorLine",this.manipulationDOM.editEdgeSpan=document.createElement("span"),this.manipulationDOM.editEdgeSpan.className="network-manipulationUI edit",this.manipulationDOM.editEdgeLabelSpan=document.createElement("span"),this.manipulationDOM.editEdgeLabelSpan.className="network-manipulationLabel",this.manipulationDOM.editEdgeLabelSpan.innerHTML=t.editEdge,this.manipulationDOM.editEdgeSpan.appendChild(this.manipulationDOM.editEdgeLabelSpan),this.manipulationDiv.appendChild(this.manipulationDOM.seperatorLineDiv3),this.manipulationDiv.appendChild(this.manipulationDOM.editEdgeSpan)),0==this._selectionIsEmpty()&&(this.manipulationDOM.seperatorLineDiv4=document.createElement("div"),this.manipulationDOM.seperatorLineDiv4.className="network-seperatorLine",this.manipulationDOM.deleteSpan=document.createElement("span"),this.manipulationDOM.deleteSpan.className="network-manipulationUI delete",this.manipulationDOM.deleteLabelSpan=document.createElement("span"),this.manipulationDOM.deleteLabelSpan.className="network-manipulationLabel",this.manipulationDOM.deleteLabelSpan.innerHTML=t.del,this.manipulationDOM.deleteSpan.appendChild(this.manipulationDOM.deleteLabelSpan),this.manipulationDiv.appendChild(this.manipulationDOM.seperatorLineDiv4),this.manipulationDiv.appendChild(this.manipulationDOM.deleteSpan)),this.manipulationDOM.addNodeSpan.onclick=this._createAddNodeToolbar.bind(this),this.manipulationDOM.addEdgeSpan.onclick=this._createAddEdgeToolbar.bind(this),1==this._getSelectedNodeCount()&&this.triggerFunctions.edit?this.manipulationDOM.editNodeSpan.onclick=this._editNode.bind(this):1==this._getSelectedEdgeCount()&&0==this._getSelectedNodeCount()&&(this.manipulationDOM.editEdgeSpan.onclick=this._createEditEdgeToolbar.bind(this)),0==this._selectionIsEmpty()&&(this.manipulationDOM.deleteSpan.onclick=this._deleteSelected.bind(this)),this.closeDiv.onclick=this._toggleEditMode.bind(this);var e=this;this.boundFunction=e._createManipulatorBar,this.on("select",this.boundFunction)}else{for(;this.editModeDiv.hasChildNodes();)this.editModeDiv.removeChild(this.editModeDiv.firstChild);this.manipulationDOM.editModeSpan=document.createElement("span"),this.manipulationDOM.editModeSpan.className="network-manipulationUI edit editmode",this.manipulationDOM.editModeLabelSpan=document.createElement("span"),this.manipulationDOM.editModeLabelSpan.className="network-manipulationLabel",this.manipulationDOM.editModeLabelSpan.innerHTML=t.edit,this.manipulationDOM.editModeSpan.appendChild(this.manipulationDOM.editModeLabelSpan),this.editModeDiv.appendChild(this.manipulationDOM.editModeSpan),this.manipulationDOM.editModeSpan.onclick=this._toggleEditMode.bind(this)}},e._createAddNodeToolbar=function(){this._clearManipulatorBar(),this.boundFunction&&this.off("select",this.boundFunction);var t=this.constants.locales[this.constants.locale];this.manipulationDOM={},this.manipulationDOM.backSpan=document.createElement("span"),this.manipulationDOM.backSpan.className="network-manipulationUI back",this.manipulationDOM.backLabelSpan=document.createElement("span"),this.manipulationDOM.backLabelSpan.className="network-manipulationLabel",this.manipulationDOM.backLabelSpan.innerHTML=t.back,this.manipulationDOM.backSpan.appendChild(this.manipulationDOM.backLabelSpan),this.manipulationDOM.seperatorLineDiv1=document.createElement("div"),this.manipulationDOM.seperatorLineDiv1.className="network-seperatorLine",this.manipulationDOM.descriptionSpan=document.createElement("span"),this.manipulationDOM.descriptionSpan.className="network-manipulationUI none",this.manipulationDOM.descriptionLabelSpan=document.createElement("span"),this.manipulationDOM.descriptionLabelSpan.className="network-manipulationLabel",this.manipulationDOM.descriptionLabelSpan.innerHTML=t.addDescription,this.manipulationDOM.descriptionSpan.appendChild(this.manipulationDOM.descriptionLabelSpan),this.manipulationDiv.appendChild(this.manipulationDOM.backSpan),this.manipulationDiv.appendChild(this.manipulationDOM.seperatorLineDiv1),this.manipulationDiv.appendChild(this.manipulationDOM.descriptionSpan),this.manipulationDOM.backSpan.onclick=this._createManipulatorBar.bind(this);var e=this;this.boundFunction=e._addNode,this.on("select",this.boundFunction)},e._createAddEdgeToolbar=function(){this._clearManipulatorBar(),this._unselectAll(!0),this.freezeSimulationEnabled=!0,this.boundFunction&&this.off("select",this.boundFunction);var t=this.constants.locales[this.constants.locale];this._unselectAll(),this.forceAppendSelection=!1,this.blockConnectingEdgeSelection=!0,this.manipulationDOM={},this.manipulationDOM.backSpan=document.createElement("span"),this.manipulationDOM.backSpan.className="network-manipulationUI back",this.manipulationDOM.backLabelSpan=document.createElement("span"),this.manipulationDOM.backLabelSpan.className="network-manipulationLabel",this.manipulationDOM.backLabelSpan.innerHTML=t.back,this.manipulationDOM.backSpan.appendChild(this.manipulationDOM.backLabelSpan),this.manipulationDOM.seperatorLineDiv1=document.createElement("div"),this.manipulationDOM.seperatorLineDiv1.className="network-seperatorLine",this.manipulationDOM.descriptionSpan=document.createElement("span"),this.manipulationDOM.descriptionSpan.className="network-manipulationUI none",this.manipulationDOM.descriptionLabelSpan=document.createElement("span"),this.manipulationDOM.descriptionLabelSpan.className="network-manipulationLabel",this.manipulationDOM.descriptionLabelSpan.innerHTML=t.edgeDescription,this.manipulationDOM.descriptionSpan.appendChild(this.manipulationDOM.descriptionLabelSpan),this.manipulationDiv.appendChild(this.manipulationDOM.backSpan),this.manipulationDiv.appendChild(this.manipulationDOM.seperatorLineDiv1),this.manipulationDiv.appendChild(this.manipulationDOM.descriptionSpan),this.manipulationDOM.backSpan.onclick=this._createManipulatorBar.bind(this);var e=this;this.boundFunction=e._handleConnect,this.on("select",this.boundFunction),this.cachedFunctions._handleTouch=this._handleTouch,this.cachedFunctions._manipulationReleaseOverload=this._manipulationReleaseOverload,this.cachedFunctions._handleDragStart=this._handleDragStart,this.cachedFunctions._handleDragEnd=this._handleDragEnd,this.cachedFunctions._handleOnHold=this._handleOnHold,this._handleTouch=this._handleConnect,this._manipulationReleaseOverload=function(){},this._handleOnHold=function(){},this._handleDragStart=function(){},this._handleDragEnd=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();var t=this.constants.locales[this.constants.locale];this.manipulationDOM={},this.manipulationDOM.backSpan=document.createElement("span"),this.manipulationDOM.backSpan.className="network-manipulationUI back",this.manipulationDOM.backLabelSpan=document.createElement("span"),this.manipulationDOM.backLabelSpan.className="network-manipulationLabel",this.manipulationDOM.backLabelSpan.innerHTML=t.back,this.manipulationDOM.backSpan.appendChild(this.manipulationDOM.backLabelSpan),this.manipulationDOM.seperatorLineDiv1=document.createElement("div"),this.manipulationDOM.seperatorLineDiv1.className="network-seperatorLine",this.manipulationDOM.descriptionSpan=document.createElement("span"),this.manipulationDOM.descriptionSpan.className="network-manipulationUI none",this.manipulationDOM.descriptionLabelSpan=document.createElement("span"),this.manipulationDOM.descriptionLabelSpan.className="network-manipulationLabel",this.manipulationDOM.descriptionLabelSpan.innerHTML=t.editEdgeDescription,this.manipulationDOM.descriptionSpan.appendChild(this.manipulationDOM.descriptionLabelSpan),this.manipulationDiv.appendChild(this.manipulationDOM.backSpan),this.manipulationDiv.appendChild(this.manipulationDOM.seperatorLineDiv1),this.manipulationDiv.appendChild(this.manipulationDOM.descriptionSpan),this.manipulationDOM.backSpan.onclick=this._createManipulatorBar.bind(this),this.cachedFunctions._handleTouch=this._handleTouch,this.cachedFunctions._manipulationReleaseOverload=this._manipulationReleaseOverload,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._manipulationReleaseOverload=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.freezeSimulationEnabled=!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.edgeBeingEdited._restoreControlNodes(),this._editEdge(e.id,this.edgeBeingEdited.to.id),this.edgeBeingEdited.controlNodes.from.unselect()),1==this.edgeBeingEdited.controlNodes.to.selected&&(this.edgeBeingEdited._restoreControlNodes(),this._editEdge(this.edgeBeingEdited.from.id,e.id),this.edgeBeingEdited.controlNodes.to.unselect())):this.edgeBeingEdited._restoreControlNodes(),this.freezeSimulationEnabled=!1,this._redraw()},e._handleConnect=function(t){if(0==this._getSelectedNodeCount()){var e=this._getNodeAt(t);if(null!=e)if(e.clusterSize>1)alert(this.constants.locales[this.constants.locale].createEdgeError);else{this._selectObject(e,!1);var i=this.sectors.support.nodes;i.targetNode=new o({id:"targetNode"},{},{},this.constants);var s=i.targetNode;s.x=e.x,s.y=e.y,this.edges.connectionEdge=new n({id:"connectionEdge",from:e.id,to:s.id},this,this.constants);var r=this.edges.connectionEdge;r.from=e,r.connected=!0,r.options.smoothCurves={enabled:!0,dynamic:!1,type:"continuous",roundness:.5},r.selected=!0,r.to=s,this.cachedFunctions._handleOnDrag=this._handleOnDrag,this._handleOnDrag=function(t){var e=this._getPointer(t.gesture.center),i=this.edges.connectionEdge;i.to.x=this._XconvertDOMtoCanvas(e.x),i.to.y=this._YconvertDOMtoCanvas(e.y)},this.moving=!0,this.start()}}},e._finishConnect=function(t){if(1==this._getSelectedNodeCount()){var e=this._getPointer(t.gesture.center);this._handleOnDrag=this.cachedFunctions._handleOnDrag,delete this.cachedFunctions._handleOnDrag;var i=this.edges.connectionEdge.fromId;delete this.edges.connectionEdge,delete this.sectors.support.nodes.targetNode,delete this.sectors.support.nodes.targetViaNode;var s=this._getNodeAt(e);null!=s&&(s.clusterSize>1?alert(this.constants.locales[this.constants.locale].createEdgeError):(this._createEdge(i,s.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)throw new Error("The function for add does not support two arguments (data,callback)");var i=this;this.triggerFunctions.add(e,function(t){i.nodesData.add(t),i._createManipulatorBar(),i.moving=!0,i.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)throw new Error("The function for connect does not support two arguments (data,callback)");var s=this;this.triggerFunctions.connect(i,function(t){s.edgesData.add(t),s.moving=!0,s.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)throw new Error("The function for edit does not support two arguments (data, callback)");var s=this;this.triggerFunctions.editEdge(i,function(t){s.edgesData.update(t),s.moving=!0,s.start()})}else this.edgesData.update(i),this.moving=!0,this.start()}},e._editNode=function(){if(!this.triggerFunctions.edit||1!=this.editMode)throw new Error("No edit function has been bound to this button");var t=this._getSelectedNode(),e={id:t.id,label:t.label,group:t.options.group,shape:t.options.shape,color:{background:t.options.color.background,border:t.options.color.border,highlight:{background:t.options.color.highlight.background,border:t.options.color.highlight.border}}};if(2!=this.triggerFunctions.edit.length)throw new Error("The function for edit does not support two arguments (data, callback)");var i=this;this.triggerFunctions.edit(e,function(t){i.nodesData.update(t),i._createManipulatorBar(),i.moving=!0,i.start()})},e._deleteSelected=function(){if(!this._selectionIsEmpty()&&1==this.editMode)if(this._clusterInSelection())alert(this.constants.locales[this.constants.locale].deleteClusterError);else{var t=this.getSelectedNodes(),e=this.getSelectedEdges();if(this.triggerFunctions.del){var i=this,s={nodes:t,edges:e};if(2!=this.triggerFunctions.del.length)throw new Error("The function for delete does not support two arguments (data, callback)");this.triggerFunctions.del(s,function(t){i.edgesData.remove(t.edges),i.nodesData.remove(t.nodes),i._unselectAll(),i.moving=!0,i.start()})}else this.edgesData.remove(e),this.nodesData.remove(t),this._unselectAll(),this.moving=!0,this.start()}}},function(t,e,i){var s=(i(1),i(45));e._cleanNavigation=function(){if(0!=this.navigationHammers.existing.length){for(var t=0;t0){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,o.edges.length>1&&this._setLevel(t+1,o.edges,o.id))}},e._setLevelDirected=function(t,e,i){this.nodes[i].hierarchyEnumerated=!0;for(var s,o,n=0;n1&&s.hierarchyEnumerated===!1&&this._setLevelDirected(s.level,s.edges,s.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 d;d=document.getElementById("graph_BH_gc"),d.onchange=a.bind(this,"graph_BH_gc",-1,"physics_barnesHut_gravitationalConstant"),d=document.getElementById("graph_BH_cg"),d.onchange=a.bind(this,"graph_BH_cg",1,"physics_centralGravity"),d=document.getElementById("graph_BH_sc"),d.onchange=a.bind(this,"graph_BH_sc",1,"physics_springConstant"),d=document.getElementById("graph_BH_sl"),d.onchange=a.bind(this,"graph_BH_sl",1,"physics_springLength"),d=document.getElementById("graph_BH_damp"),d.onchange=a.bind(this,"graph_BH_damp",1,"physics_damping"),d=document.getElementById("graph_R_nd"),d.onchange=a.bind(this,"graph_R_nd",1,"physics_repulsion_nodeDistance"),d=document.getElementById("graph_R_cg"),d.onchange=a.bind(this,"graph_R_cg",1,"physics_centralGravity"),d=document.getElementById("graph_R_sc"),d.onchange=a.bind(this,"graph_R_sc",1,"physics_springConstant"),d=document.getElementById("graph_R_sl"),d.onchange=a.bind(this,"graph_R_sl",1,"physics_springLength"),d=document.getElementById("graph_R_damp"),d.onchange=a.bind(this,"graph_R_damp",1,"physics_damping"),d=document.getElementById("graph_H_nd"),d.onchange=a.bind(this,"graph_H_nd",1,"physics_hierarchicalRepulsion_nodeDistance"),d=document.getElementById("graph_H_cg"),d.onchange=a.bind(this,"graph_H_cg",1,"physics_centralGravity"),d=document.getElementById("graph_H_sc"),d.onchange=a.bind(this,"graph_H_sc",1,"physics_springConstant"),d=document.getElementById("graph_H_sl"),d.onchange=a.bind(this,"graph_H_sl",1,"physics_springLength"),d=document.getElementById("graph_H_damp"),d.onchange=a.bind(this,"graph_H_damp",1,"physics_damping"),d=document.getElementById("graph_H_direction"),d.onchange=a.bind(this,"graph_H_direction",i,"hierarchicalLayout_direction"),d=document.getElementById("graph_H_levsep"),d.onchange=a.bind(this,"graph_H_levsep",1,"hierarchicalLayout_levelSeparation"),d=document.getElementById("graph_H_nspac"),d.onchange=a.bind(this,"graph_H_nspac",1,"hierarchicalLayout_nodeSpacing");var l=document.getElementById("graph_physicsMethod1"),c=document.getElementById("graph_physicsMethod2"),p=document.getElementById("graph_physicsMethod3");c.checked=!0,this.constants.physics.barnesHut.enabled&&(l.checked=!0),this.constants.hierarchicalLayout.enabled&&(p.checked=!0);var u=document.getElementById("graph_toggleSmooth"),m=document.getElementById("graph_repositionNodes"),f=document.getElementById("graph_generateOptions");u.onclick=s.bind(this),m.onclick=o.bind(this),f.onclick=n.bind(this),u.style.background=1==this.constants.smoothCurves&&0==this.constants.dynamicSmoothCurves?"#A4FF56":"#FF8532",r.apply(this),l.onchange=r.bind(this),c.onchange=r.bind(this),p.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){function e(t){throw new Error("Cannot find module '"+t+"'.")}e.keys=function(){return[]},e.resolve=e,t.exports=e,e.id=67},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,f=this.constants.physics.repulsion.nodeDistance,g=f;for(d=0;di&&(r=.5*g>i?1:v*i+m,r*=0==n?1:1+n*this.constants.clustering.forceAmplification,r/=Math.max(i,.01*g),s=t*r,o=e*r,a.fx-=s,a.fy-=o,h.fx+=s,h.fy+=o)}}},function(t,e){e._calculateNodeForces=function(){var t,e,i,s,o,n,r,a,h,d,l=this.calculationNodes,c=this.calculationNodeIndices,p=this.constants.physics.hierarchicalRepulsion.nodeDistance;for(h=0;hi?-Math.pow(u*i,2)+Math.pow(u*p,2):0,0==i?i=.01:n/=i,s=t*n,o=e*n,r.fx-=s,r.fy-=o,a.fx+=s,a.fy+=o}},e._calculateHierarchicalSpringForces=function(){for(var t,e,i,s,o,n,r,a,h,d=this.edges,l=this.calculationNodes,c=this.calculationNodeIndices,p=0;pn;n++)t=e[i[n]],t.options.mass>0&&(this._getForceContribution(o.root.children.NW,t),this._getForceContribution(o.root.children.NE,t),this._getForceContribution(o.root.children.SW,t),this._getForceContribution(o.root.children.SE,t))}},e._getForceContribution=function(t,e){if(t.childrenCount>0){var i,s,o;if(i=t.centerOfMass.x-e.x,s=t.centerOfMass.y-e.y,o=Math.sqrt(i*i+s*s),o*t.calcSize>this.constants.physics.barnesHut.thetaInverted){0==o&&(o=.1*Math.random(),i=o);var n=this.constants.physics.barnesHut.gravitationalConstant*t.mass*e.options.mass/(o*o*o),r=i*n,a=s*n;e.fx+=r,e.fy+=a}else if(4==t.childrenCount)this._getForceContribution(t.children.NW,e),this._getForceContribution(t.children.NE,e),this._getForceContribution(t.children.SW,e),this._getForceContribution(t.children.SE,e);else if(t.children.data.id!=e.id){0==o&&(o=.5*Math.random(),i=o);var n=this.constants.physics.barnesHut.gravitationalConstant*t.mass*e.options.mass/(o*o*o),r=i*n,a=s*n;e.fx+=r,e.fy+=a}}},e._formBarnesHutTree=function(t,e){for(var i,s=e.length,o=Number.MAX_VALUE,n=Number.MAX_VALUE,r=-Number.MAX_VALUE,a=-Number.MAX_VALUE,h=0;s>h;h++){var d=t[e[h]].x,l=t[e[h]].y;t[e[h]].options.mass>0&&(o>d&&(o=d),d>r&&(r=d),n>l&&(n=l),l>a&&(a=l))}var c=Math.abs(r-o)-Math.abs(a-n);c>0?(n-=.5*c,a+=.5*c):(o+=.5*c,r-=.5*c);var p=1e-5,u=Math.max(p,Math.abs(r-o)),m=.5*u,f=.5*(o+r),g=.5*(n+a),v={root:{centerOfMass:{x:0,y:0},mass:0,range:{minX:f-m,maxX:f+m,minY:g-m,maxY:g+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]],i.options.mass>0&&this._placeInTree(v.root,i);this.barnesHutTree=v},e._updateBranchMass=function(t,e){var i=t.mass+e.options.mass,s=1/i;t.centerOfMass.x=t.centerOfMass.x*t.mass+e.x*e.options.mass,t.centerOfMass.x*=s,t.centerOfMass.y=t.centerOfMass.y*t.mass+e.y*e.options.mass,t.centerOfMass.y*=s,t.mass=i;var o=Math.max(Math.max(e.height,e.radius),e.width);t.maxWidth=t.maxWidthe.x?t.children.NW.range.maxY>e.y?this._placeInRegion(t,e,"NW"):this._placeInRegion(t,e,"SW"):t.children.NW.range.maxY>e.y?this._placeInRegion(t,e,"NE"):this._placeInRegion(t,e,"SE")},e._placeInRegion=function(t,e,i){switch(t.children[i].childrenCount){case 0:t.children[i].children.data=e,t.children[i].childrenCount=1,this._updateBranchMass(t.children[i],e);break;case 1:t.children[i].children.data.x==e.x&&t.children[i].children.data.y==e.y?(e.x+=Math.random(),e.y+=Math.random()):(this._splitBranch(t.children[i]),this._placeInTree(t.children[i],e));break;case 4:this._placeInTree(t.children[i],e)}},e._splitBranch=function(t){var e=null;1==t.childrenCount&&(e=t.children.data,t.mass=0,t.centerOfMass.x=0,t.centerOfMass.y=0),t.childrenCount=4,t.children.data=null,this._insertRegion(t,"NW"),this._insertRegion(t,"NE"),this._insertRegion(t,"SW"),this._insertRegion(t,"SE"),null!=e&&this._placeInTree(t,e)},e._insertRegion=function(t,e){var i,s,o,n,r=.5*t.size;switch(e){case"NW":i=t.range.minX,s=t.range.minX+r,o=t.range.minY,n=t.range.minY+r;break;case"NE":i=t.range.minX+r,s=t.range.maxX,o=t.range.minY,n=t.range.minY+r;break;case"SW":i=t.range.minX,s=t.range.minX+r,o=t.range.minY+r,n=t.range.maxY;break;case"SE":i=t.range.minX+r,s=t.range.maxX,o=t.range.minY+r,n=t.range.maxY}t.children[e]={centerOfMass:{x:0,y:0},mass:0,range:{minX:i,maxX:s,minY:o,maxY:n},size:.5*t.size,calcSize:2*t.calcSize,children:{data:null},maxWidth:0,level:t.level+1,childrenCount:0}},e._drawTree=function(t,e){void 0!==this.barnesHutTree&&(t.lineWidth=1,this._drawBranch(this.barnesHutTree.root,t,e))},e._drawBranch=function(t,e,i){void 0===i&&(i="#FF0000"),4==t.childrenCount&&(this._drawBranch(t.children.NW,e),this._drawBranch(t.children.NE,e),this._drawBranch(t.children.SE,e),this._drawBranch(t.children.SW,e)),e.strokeStyle=i,e.beginPath(),e.moveTo(t.range.minX,t.range.minY),e.lineTo(t.range.maxX,t.range.minY),e.stroke(),e.beginPath(),e.moveTo(t.range.maxX,t.range.minY),e.lineTo(t.range.maxX,t.range.maxY),e.stroke(),e.beginPath(),e.moveTo(t.range.maxX,t.range.maxY),e.lineTo(t.range.minX,t.range.maxY),e.stroke(),e.beginPath(),e.moveTo(t.range.minX,t.range.maxY),e.lineTo(t.range.minX,t.range.minY),e.stroke()}},function(t){t.exports=function(t){return t.webpackPolyfill||(t.deprecate=function(){},t.paths=[],t.children=[],t.webpackPolyfill=1),t}}])}); +"use strict";!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(6),e.DataSet=i(7),e.DataView=i(9),e.Queue=i(8),e.Graph3d=i(10),e.graph3d={Camera:i(14),Filter:i(15),Point2d:i(13),Point3d:i(12),Slider:i(16),StepNumber:i(17)},e.Timeline=i(18),e.Graph2d=i(42),e.timeline={DateUtil:i(24),DataStep:i(45),Range:i(21),stack:i(29),TimeStep:i(27),components:{items:{Item:i(31),BackgroundItem:i(35),BoxItem:i(33),PointItem:i(34),RangeItem:i(30)},Component:i(23),CurrentTime:i(39),CustomTime:i(41),DataAxis:i(44),GraphGroup:i(46),Group:i(28),BackgroundGroup:i(32),ItemSet:i(26),Legend:i(50),LineGraph:i(43),TimeAxis:i(38)}},e.Network=i(51),e.network={Edge:i(52),Groups:i(54),Images:i(55),Node:i(53),Popup:i(56),dotparser:i(57),gephiParser:i(58)},e.Graph=function(){throw new Error("Graph is renamed to Network. Please create a graph as new vis.Network(...)")},e.moment=i(2),e.hammer=i(19)},function(t,e,i){var s=i(2);e.isNumber=function(t){return t instanceof Number||"number"==typeof t},e.giveRange=function(t,e,i,s){if(e==t)return.5;var o=1/(e-t);return Math.max(0,(s-t)*o)},e.isString=function(t){return t instanceof String||"string"==typeof t},e.isDate=function(t){if(t instanceof Date)return!0;if(e.isString(t)){var i=o.exec(t);if(i)return!0;if(!isNaN(Date.parse(t)))return!0}return!1},e.isDataTable=function(t){return"undefined"!=typeof google&&google.visualization&&google.visualization.DataTable&&t instanceof google.visualization.DataTable},e.randomUUID=function(){var t=function(){return Math.floor(65536*Math.random()).toString(16)};return t()+t()+"-"+t()+"-"+t()+"-"+t()+"-"+t()+t()+t()},e.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},e.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},e.convert=function(t,i){var n;if(void 0===t)return void 0;if(null===t)return null;if(!i)return t;if("string"!=typeof i&&!(i instanceof String))throw new Error("Type must be a string");switch(i){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(e.isNumber(t))return new Date(t);if(t instanceof Date)return new Date(t.valueOf());if(s.isMoment(t))return new Date(t.valueOf());if(e.isString(t))return n=o.exec(t),n?new Date(Number(n[1])):s(t).toDate();throw new Error("Cannot convert object of type "+e.getType(t)+" to type Date");case"Moment":if(e.isNumber(t))return s(t);if(t instanceof Date)return s(t.valueOf());if(s.isMoment(t))return s(t);if(e.isString(t))return n=o.exec(t),s(n?Number(n[1]):t);throw new Error("Cannot convert object of type "+e.getType(t)+" to type Date");case"ISODate":if(e.isNumber(t))return new Date(t);if(t instanceof Date)return t.toISOString();if(s.isMoment(t))return t.toDate().toISOString();if(e.isString(t))return n=o.exec(t),n?new Date(Number(n[1])).toISOString():new Date(t).toISOString();throw new Error("Cannot convert object of type "+e.getType(t)+" to type ISODate");case"ASPDate":if(e.isNumber(t))return"/Date("+t+")/";if(t instanceof Date)return"/Date("+t.valueOf()+")/";if(e.isString(t)){n=o.exec(t);var r;return r=n?new Date(Number(n[1])).valueOf():new Date(t).valueOf(),"/Date("+r+")/"}throw new Error("Cannot convert object of type "+e.getType(t)+" to type ASPDate");default:throw new Error('Unknown type "'+i+'"')}};var o=/^\/?Date\((\-?\d+)/i;e.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":Array.isArray(t)?"Array":t instanceof Date?"Date":"Object":"number"==e?"Number":"boolean"==e?"Boolean":"string"==e?"String":e},e.getAbsoluteLeft=function(t){return t.getBoundingClientRect().left+window.pageXOffset},e.getAbsoluteTop=function(t){return t.getBoundingClientRect().top+window.pageYOffset},e.addClassName=function(t,e){var i=t.className.split(" ");-1==i.indexOf(e)&&(i.push(e),t.className=i.join(" "))},e.removeClassName=function(t,e){var i=t.className.split(" "),s=i.indexOf(e);-1!=s&&(i.splice(s,1),t.className=i.join(" "))},e.forEach=function(t,e){var i,s;if(Array.isArray(t))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)},e.toArray=function(t){var e=[];for(var i in t)t.hasOwnProperty(i)&&e.push(t[i]);return e},e.updateProperty=function(t,e,i){return t[e]!==i?(t[e]=i,!0):!1},e.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)},e.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)},e.preventDefault=function(t){t||(t=window.event),t.preventDefault?t.preventDefault():t.returnValue=!1},e.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},e.option={},e.option.asBoolean=function(t,e){return"function"==typeof t&&(t=t()),null!=t?0!=t:e||null},e.option.asNumber=function(t,e){return"function"==typeof t&&(t=t()),null!=t?Number(t)||e||null:e||null},e.option.asString=function(t,e){return"function"==typeof t&&(t=t()),null!=t?String(t):e||null},e.option.asSize=function(t,i){return"function"==typeof t&&(t=t()),e.isString(t)?t:e.isNumber(t)?t+"px":i||null},e.option.asElement=function(t,e){return"function"==typeof t&&(t=t()),t||e||null},e.hexToRGB=function(t){var e=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;t=t.replace(e,function(t,e,i,s){return e+e+i+i+s+s});var i=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);return i?{r:parseInt(i[1],16),g:parseInt(i[2],16),b:parseInt(i[3],16)}:null},e.overrideOpacity=function(t,i){if(-1!=t.indexOf("rgb")){var s=t.substr(t.indexOf("(")+1).replace(")","").split(",");return"rgba("+s[0]+","+s[1]+","+s[2]+","+i+")"}var s=e.hexToRGB(t);return null==s?t:"rgba("+s.r+","+s.g+","+s.b+","+i+")"},e.RGBToHex=function(t,e,i){return"#"+((1<<24)+(t<<16)+(e<<8)+i).toString(16).slice(1)},e.parseColor=function(t){var i;if(e.isString(t)){if(e.isValidRGB(t)){var s=t.substr(4).substr(0,t.length-5).split(",");t=e.RGBToHex(s[0],s[1],s[2])}if(e.isValidHex(t)){var o=e.hexToHSV(t),n={h:o.h,s:.45*o.s,v:Math.min(1,1.05*o.v)},r={h:o.h,s:Math.min(1,1.25*o.v),v:.6*o.v},a=e.HSVToHex(r.h,r.h,r.v),h=e.HSVToHex(n.h,n.s,n.v);i={background:t,border:a,highlight:{background:h,border:a},hover:{background:h,border:a}}}else i={background:t,border:t,highlight:{background:t,border:t},hover:{background:t,border:t}}}else i={},i.background=t.background||"white",i.border=t.border||i.background,e.isString(t.highlight)?i.highlight={border:t.highlight,background:t.highlight}:(i.highlight={},i.highlight.background=t.highlight&&t.highlight.background||i.background,i.highlight.border=t.highlight&&t.highlight.border||i.border),e.isString(t.hover)?i.hover={border:t.hover,background:t.hover}:(i.hover={},i.hover.background=t.hover&&t.hover.background||i.background,i.hover.border=t.hover&&t.hover.border||i.border);return i},e.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}};var n={split:function(t){var e={};return t.split(";").forEach(function(t){if(""!=t.trim()){var i=t.split(":"),s=i[0].trim(),o=i[1].trim();e[s]=o}}),e},join:function(t){return Object.keys(t).map(function(e){return e+": "+t[e]}).join("; ")}};e.addCssText=function(t,i){var s=n.split(t.style.cssText),o=n.split(i),r=e.extend(s,o);t.style.cssText=n.join(r)},e.removeCssText=function(t,e){var i=n.split(t.style.cssText),s=n.split(e);for(var o in s)s.hasOwnProperty(o)&&delete i[o];t.style.cssText=n.join(i)},e.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)}},e.HSVToHex=function(t,i,s){var o=e.HSVToRGB(t,i,s);return e.RGBToHex(o.r,o.g,o.b)},e.hexToHSV=function(t){var i=e.hexToRGB(t);return e.RGBToHSV(i.r,i.g,i.b)},e.isValidHex=function(t){var e=/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(t);return e},e.isValidRGB=function(t){t=t.replace(" ","");var e=/rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)/i.test(t);return e},e.selectiveBridgeObject=function(t,i){if("object"==typeof i){for(var s=Object.create(i),o=0;o=r&&o>n;){var h=Math.floor((r+a)/2),d=t[h],l=void 0===s?d[i]:d[i][s],c=e(l);if(0==c)return h;-1==c?r=h+1:a=h-1,n++}return-1},e.binarySearchValue=function(t,e,i,s){for(var o,n,r,a,h=1e4,d=0,l=0,c=t.length-1;c>=l&&h>d;){if(a=Math.floor(.5*(c+l)),o=t[Math.max(0,a-1)][i],n=t[a][i],r=t[Math.min(t.length-1,a+1)][i],n==e)return a;if(e>o&&n>e)return"before"==s?Math.max(0,a-1):a;if(e>n&&r>e)return"before"==s?a:Math.min(t.length-1,a+1);e>n?l=a+1:c=a-1,d++}return-1},e.easeInOutQuad=function(t,e,i,s){var o=i-e;return t/=s/2,1>t?o/2*t*t+e:(t--,-o/2*(t*(t-2)-1)+e)},e.easingFunctions={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return t*(2-t)},easeInOutQuad:function(t){return.5>t?2*t*t:-1+(4-2*t)*t},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return--t*t*t+1},easeInOutCubic:function(t){return.5>t?4*t*t*t:(t-1)*(2*t-2)*(2*t-2)+1},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return 1- --t*t*t*t},easeInOutQuart:function(t){return.5>t?8*t*t*t*t:1-8*--t*t*t*t},easeInQuint:function(t){return t*t*t*t*t},easeOutQuint:function(t){return 1+--t*t*t*t*t},easeInOutQuint:function(t){return.5>t?16*t*t*t*t*t:1+16*--t*t*t*t*t}}},function(t,e,i){t.exports="undefined"!=typeof window&&window.moment||i(3)},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(t,e){return Le.call(t,e)}function h(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1}}function d(t){Ce.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+t)}function l(t,e){var i=!0;return b(function(){return i&&(d(t),i=!1),e.apply(this,arguments)},e)}function c(t,e){Di[t]||(d(e),Di[t]=!0)}function p(t,e){return function(i){return w(t.call(this,i),e)}}function u(t,e){return function(i){return this.localeData().ordinal(t.call(this,i),e)}}function m(t,e){var i,s,o=12*(e.year()-t.year())+(e.month()-t.month()),n=t.clone().add(o,"months");return 0>e-n?(i=t.clone().add(o-1,"months"),s=(e-n)/(n-i)):(i=t.clone().add(o+1,"months"),s=(e-n)/(i-n)),-(o+s)}function f(t,e,i){var s;return null==i?e:null!=t.meridiemHour?t.meridiemHour(e,i):null!=t.isPM?(s=t.isPM(i),s&&12>e&&(e+=12),s||12!==e||(e=0),e):e}function g(){}function v(t,e){e!==!1&&F(t),_(this,t),this._d=new Date(+t._d),Si===!1&&(Si=!0,Ce.updateOffset(this),Si=!1)}function y(t){var e=N(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._locale=Ce.localeData(),this._bubble()}function b(t,e){for(var i in e)a(e,i)&&(t[i]=e[i]);return a(e,"toString")&&(t.toString=e.toString),a(e,"valueOf")&&(t.valueOf=e.valueOf),t}function _(t,e){var i,s,o;if("undefined"!=typeof e._isAMomentObject&&(t._isAMomentObject=e._isAMomentObject),"undefined"!=typeof e._i&&(t._i=e._i),"undefined"!=typeof e._f&&(t._f=e._f),"undefined"!=typeof e._l&&(t._l=e._l),"undefined"!=typeof e._strict&&(t._strict=e._strict),"undefined"!=typeof e._tzm&&(t._tzm=e._tzm),"undefined"!=typeof e._isUTC&&(t._isUTC=e._isUTC),"undefined"!=typeof e._offset&&(t._offset=e._offset),"undefined"!=typeof e._pf&&(t._pf=e._pf),"undefined"!=typeof e._locale&&(t._locale=e._locale),Ye.length>0)for(i in Ye)s=Ye[i],o=e[s],"undefined"!=typeof o&&(t[s]=o);return t}function x(t){return 0>t?Math.ceil(t):Math.floor(t)}function w(t,e,i){for(var s=""+Math.abs(t),o=t>=0;s.lengths;s++)(i&&t[s]!==e[s]||!i&&I(t[s])!==I(e[s]))&&r++;return r+n}function E(t){if(t){var e=t.toLowerCase().replace(/(.)s$/,"$1");t=gi[t]||vi[e]||e}return t}function N(t){var e,i,s={};for(i in t)a(t,i)&&(e=E(i),e&&(s[e]=t[i]));return s}function L(t){var e,i;if(0===t.indexOf("week"))e=7,i="day";else{if(0!==t.indexOf("month"))return;e=12,i="month"}Ce[t]=function(s,o){var r,a,h=Ce._locale[t],d=[];if("number"==typeof s&&(o=s,s=n),a=function(t){var e=Ce().utc().set(i,t);return h.call(Ce._locale,e,s||"")},null!=o)return a(o);for(r=0;e>r;r++)d.push(a(r));return d}}function I(t){var e=+t,i=0;return 0!==e&&isFinite(e)&&(i=e>=0?Math.floor(e):Math.ceil(e)),i}function z(t,e){return new Date(Date.UTC(t,e+1,0)).getUTCDate()}function A(t,e,i){return me(Ce([t,11,31+e-i]),e,i).week}function P(t){return R(t)?366:365}function R(t){return t%4===0&&t%100!==0||t%400===0}function F(t){var e;t._a&&-2===t._pf.overflow&&(e=t._a[ze]<0||t._a[ze]>11?ze:t._a[Ae]<1||t._a[Ae]>z(t._a[Ie],t._a[ze])?Ae:t._a[Pe]<0||t._a[Pe]>24||24===t._a[Pe]&&(0!==t._a[Re]||0!==t._a[Fe]||0!==t._a[Be])?Pe:t._a[Re]<0||t._a[Re]>59?Re:t._a[Fe]<0||t._a[Fe]>59?Fe:t._a[Be]<0||t._a[Be]>999?Be:-1,t._pf._overflowDayOfYear&&(Ie>e||e>Ae)&&(e=Ae),t._pf.overflow=e)}function B(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._pf.bigHour===n)),t._isValid}function H(t){return t?t.toLowerCase().replace("_","-"):t}function Y(t){for(var e,i,s,o,n=0;n0;){if(s=W(o.slice(0,e).join("-")))return s;if(i&&i.length>=e&&k(o,i,!0)>=e-1)break;e--}n++}return null}function W(t){var e=null;if(!He[t]&&We)try{e=Ce.locale(),!function(){var t=new Error('Cannot find module "./locale"');throw t.code="MODULE_NOT_FOUND",t}(),Ce.locale(e)}catch(i){}return He[t]}function G(t,e){var i,s;return e._isUTC?(i=e.clone(),s=(Ce.isMoment(t)||T(t)?+t:+Ce(t))-+i,i._d.setTime(+i._d+s),Ce.updateOffset(i,!1),i):Ce(t).local()}function j(t){return t.match(/\[[\s\S]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"")}function V(t){var e,i,s=t.match(Ue);for(e=0,i=s.length;i>e;e++)s[e]=wi[s[e]]?wi[s[e]]:j(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 U(t,e){return t.isValid()?(e=X(e,t.localeData()),yi[e]||(yi[e]=V(e)),yi[e](t)):t.localeData().invalidDate()}function X(t,e){function i(t){return e.longDateFormat(t)||t}var s=5;for(Xe.lastIndex=0;s>=0&&Xe.test(t);)t=t.replace(Xe,i),Xe.lastIndex=0,s-=1;return t}function q(t,e){var i,s=e._strict;switch(t){case"Q":return oi;case"DDDD":return ri;case"YYYY":case"GGGG":case"gggg":return s?ai:Qe;case"Y":case"G":case"g":return di;case"YYYYYY":case"YYYYY":case"GGGGG":case"ggggg":return s?hi:Ke;case"S":if(s)return oi;case"SS":if(s)return ni;case"SSS":if(s)return ri;case"DDD":return Ze;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":return Je;case"a":case"A":return e._locale._meridiemParse;case"x":return ii;case"X":return si;case"Z":case"ZZ":return ti;case"T":return ei;case"SSSS":return $e;case"MM":case"DD":case"YY":case"GG":case"gg":case"HH":case"hh":case"mm":case"ss":case"ww":case"WW":return s?ni:qe;case"M":case"D":case"d":case"H":case"h":case"m":case"s":case"w":case"W":case"e":case"E":return qe;case"Do":return s?e._locale._ordinalParse:e._locale._ordinalParseLenient;default:return i=new RegExp(se(ie(t.replace("\\","")),"i"))}}function Z(t){t=t||"";var e=t.match(ti)||[],i=e[e.length-1]||[],s=(i+"").match(mi)||["-",0,0],o=+(60*s[1])+I(s[2]);return"+"===s[0]?o:-o}function Q(t,e,i){var s,o=i._a;switch(t){case"Q":null!=e&&(o[ze]=3*(I(e)-1));break;case"M":case"MM":null!=e&&(o[ze]=I(e)-1);break;case"MMM":case"MMMM":s=i._locale.monthsParse(e,t,i._strict),null!=s?o[ze]=s:i._pf.invalidMonth=e;break;case"D":case"DD":null!=e&&(o[Ae]=I(e));break;case"Do":null!=e&&(o[Ae]=I(parseInt(e.match(/\d{1,2}/)[0],10)));break;case"DDD":case"DDDD":null!=e&&(i._dayOfYear=I(e));break;case"YY":o[Ie]=Ce.parseTwoDigitYear(e);break;case"YYYY":case"YYYYY":case"YYYYYY":o[Ie]=I(e);break;case"a":case"A":i._meridiem=e;break;case"h":case"hh":i._pf.bigHour=!0;case"H":case"HH":o[Pe]=I(e);break;case"m":case"mm":o[Re]=I(e);break;case"s":case"ss":o[Fe]=I(e);break;case"S":case"SS":case"SSS":case"SSSS":o[Be]=I(1e3*("0."+e));break;case"x":i._d=new Date(I(e));break;case"X":i._d=new Date(1e3*parseFloat(e));break;case"Z":case"ZZ":i._useUTC=!0,i._tzm=Z(e);break;case"dd":case"ddd":case"dddd":s=i._locale.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]=I(e));break;case"gg":case"GG":i._w=i._w||{},i._w[t]=Ce.parseTwoDigitYear(e)}}function K(t){var e,i,s,o,n,a,h;e=t._w,null!=e.GG||null!=e.W||null!=e.E?(n=1,a=4,i=r(e.GG,t._a[Ie],me(Ce(),1,4).year),s=r(e.W,1),o=r(e.E,1)):(n=t._locale._week.dow,a=t._locale._week.doy,i=r(e.gg,t._a[Ie],me(Ce(),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=fe(i,s,o,a,n),t._a[Ie]=h.year,t._dayOfYear=h.dayOfYear}function $(t){var e,i,s,o,n=[];if(!t._d){for(s=te(t),t._w&&null==t._a[Ae]&&null==t._a[ze]&&K(t),t._dayOfYear&&(o=r(t._a[Ie],s[Ie]),t._dayOfYear>P(o)&&(t._pf._overflowDayOfYear=!0),i=le(o,0,t._dayOfYear),t._a[ze]=i.getUTCMonth(),t._a[Ae]=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];24===t._a[Pe]&&0===t._a[Re]&&0===t._a[Fe]&&0===t._a[Be]&&(t._nextDay=!0,t._a[Pe]=0),t._d=(t._useUTC?le:de).apply(null,n),null!=t._tzm&&t._d.setUTCMinutes(t._d.getUTCMinutes()-t._tzm),t._nextDay&&(t._a[Pe]=24)}}function J(t){var e;t._d||(e=N(t._i),t._a=[e.year,e.month,e.day||e.date,e.hour,e.minute,e.second,e.millisecond],$(t))}function te(t){var e=new Date;return t._useUTC?[e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()]:[e.getFullYear(),e.getMonth(),e.getDate()]}function ee(t){if(t._f===Ce.ISO_8601)return void ne(t);t._a=[],t._pf.empty=!0;var e,i,s,o,r,a=""+t._i,h=a.length,d=0;for(s=X(t._f,t._locale).match(Ue)||[],e=0;e0&&t._pf.unusedInput.push(r),a=a.slice(a.indexOf(i)+i.length),d+=i.length),wi[o]?(i?t._pf.empty=!1:t._pf.unusedTokens.push(o),Q(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._pf.bigHour===!0&&t._a[Pe]<=12&&(t._pf.bigHour=n),t._a[Pe]=f(t._locale,t._a[Pe],t._meridiem),$(t),F(t)}function ie(t){return t.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(t,e,i,s,o){return e||i||s||o})}function se(t){return t.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function oe(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));b(t,i||e)}function ne(t){var e,i,s=t._i,o=li.exec(s);if(o){for(t._pf.iso=!0,e=0,i=pi.length;i>e;e++)if(pi[e][1].exec(s)){t._f=pi[e][0]+(o[6]||" ");break}for(e=0,i=ui.length;i>e;e++)if(ui[e][1].exec(s)){t._f+=ui[e][0];break}s.match(ti)&&(t._f+="Z"),ee(t)}else t._isValid=!1}function re(t){ne(t),t._isValid===!1&&(delete t._isValid,Ce.createFromInputFallback(t))}function ae(t,e){var i,s=[];for(i=0;it&&a.setFullYear(t),a}function le(t){var e=new Date(Date.UTC.apply(null,arguments));return 1970>t&&e.setUTCFullYear(t),e}function ce(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 pe(t,e,i,s,o){return o.relativeTime(e||1,!!i,t,s)}function ue(t,e,i){var s=Ce.duration(t).abs(),o=Ne(s.as("s")),n=Ne(s.as("m")),r=Ne(s.as("h")),a=Ne(s.as("d")),h=Ne(s.as("M")),d=Ne(s.as("y")),l=o0,l[4]=i,pe.apply({},l)}function me(t,e,i){var s,o=i-e,n=i-t.day();return n>o&&(n-=7),o-7>n&&(n+=7),s=Ce(t).add(n,"d"),{week:Math.ceil(s.dayOfYear()/7),year:s.year()}}function fe(t,e,i,s,o){var n,r,a=le(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:P(t-1)+r}}function ge(t){var e,i=t._i,s=t._f;return t._locale=t._locale||Ce.localeData(t._l),null===i||s===n&&""===i?Ce.invalid({nullInput:!0}):("string"==typeof i&&(t._i=i=t._locale.preparse(i)),Ce.isMoment(i)?new v(i,!0):(s?O(s)?oe(t):ee(t):he(t),e=new v(t),e._nextDay&&(e.add(1,"d"),e._nextDay=n),e))}function ve(t,e){var i,s;if(1===e.length&&O(e[0])&&(e=e[0]),!e.length)return Ce();for(i=e[0],s=1;s=0?"+":"-";return e+w(Math.abs(t),6)},gg:function(){return w(this.weekYear()%100,2)},gggg:function(){return w(this.weekYear(),4)},ggggg:function(){return w(this.weekYear(),5)},GG:function(){return w(this.isoWeekYear()%100,2)},GGGG:function(){return w(this.isoWeekYear(),4)},GGGGG:function(){return w(this.isoWeekYear(),5)},e:function(){return this.weekday()},E:function(){return this.isoWeekday()},a:function(){return this.localeData().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.localeData().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 I(this.milliseconds()/100)},SS:function(){return w(I(this.milliseconds()/10),2)},SSS:function(){return w(this.milliseconds(),3)},SSSS:function(){return w(this.milliseconds(),3)},Z:function(){var t=this.utcOffset(),e="+";return 0>t&&(t=-t,e="-"),e+w(I(t/60),2)+":"+w(I(t)%60,2)},ZZ:function(){var t=this.utcOffset(),e="+";return 0>t&&(t=-t,e="-"),e+w(I(t/60),2)+w(I(t)%60,2)},z:function(){return this.zoneAbbr()},zz:function(){return this.zoneName()},x:function(){return this.valueOf()},X:function(){return this.unix()},Q:function(){return this.quarter()}},Di={},Mi=["months","monthsShort","weekdays","weekdaysShort","weekdaysMin"],Si=!1;_i.length;)Te=_i.pop(),wi[Te+"o"]=u(wi[Te],Te);for(;xi.length;)Te=xi.pop(),wi[Te+Te]=p(wi[Te],2);wi.DDDD=p(wi.DDD,3),b(g.prototype,{set:function(t){var e,i;for(i in t)e=t[i],"function"==typeof e?this[i]=e:this["_"+i]=e;this._ordinalParseLenient=new RegExp(this._ordinalParse.source+"|"+/\d{1,2}/.source)},_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,e,i){var s,o,n;for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),s=0;12>s;s++){if(o=Ce.utc([2e3,s]),i&&!this._longMonthsParse[s]&&(this._longMonthsParse[s]=new RegExp("^"+this.months(o,"").replace(".","")+"$","i"),this._shortMonthsParse[s]=new RegExp("^"+this.monthsShort(o,"").replace(".","")+"$","i")),i||this._monthsParse[s]||(n="^"+this.months(o,"")+"|^"+this.monthsShort(o,""),this._monthsParse[s]=new RegExp(n.replace(".",""),"i")),i&&"MMMM"===e&&this._longMonthsParse[s].test(t))return s;if(i&&"MMM"===e&&this._shortMonthsParse[s].test(t))return s;if(!i&&this._monthsParse[s].test(t))return s}},_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=Ce([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:{LTS:"h:mm:ss A",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,i){var s=this._calendar[t];return"function"==typeof s?s.apply(e,[i]):s},_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",_ordinalParse:/\d{1,2}/,preparse:function(t){return t},postformat:function(t){return t},week:function(t){return me(t,this._week.dow,this._week.doy).week},_week:{dow:0,doy:6},firstDayOfWeek:function(){return this._week.dow},firstDayOfYear:function(){return this._week.doy},_invalidDate:"Invalid date",invalidDate:function(){return this._invalidDate}}),Ce=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=h(),ge(o)},Ce.suppressDeprecationWarnings=!1,Ce.createFromInputFallback=l("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+(t._useUTC?" UTC":""))}),Ce.min=function(){var t=[].slice.call(arguments,0);return ve("isBefore",t)},Ce.max=function(){var t=[].slice.call(arguments,0);return ve("isAfter",t)},Ce.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=h(),ge(o).utc()},Ce.unix=function(t){return Ce(1e3*t)},Ce.duration=function(t,e){var i,s,o,n,r=t,h=null;return Ce.isDuration(t)?r={ms:t._milliseconds,d:t._days,M:t._months}:"number"==typeof t?(r={},e?r[e]=t:r.milliseconds=t):(h=je.exec(t))?(i="-"===h[1]?-1:1,r={y:0,d:I(h[Ae])*i,h:I(h[Pe])*i,m:I(h[Re])*i,s:I(h[Fe])*i,ms:I(h[Be])*i}):(h=Ve.exec(t))?(i="-"===h[1]?-1:1,o=function(t){var e=t&&parseFloat(t.replace(",","."));return(isNaN(e)?0:e)*i},r={y:o(h[2]),M:o(h[3]),d:o(h[4]),h:o(h[5]),m:o(h[6]),s:o(h[7]),w:o(h[8])}):null==r?r={}:"object"==typeof r&&("from"in r||"to"in r)&&(n=M(Ce(r.from),Ce(r.to)),r={},r.ms=n.milliseconds,r.M=n.months),s=new y(r),Ce.isDuration(t)&&a(t,"_locale")&&(s._locale=t._locale),s},Ce.version=ke,Ce.defaultFormat=ci,Ce.ISO_8601=function(){},Ce.momentProperties=Ye,Ce.updateOffset=function(){},Ce.relativeTimeThreshold=function(t,e){return bi[t]===n?!1:e===n?bi[t]:(bi[t]=e,!0)},Ce.lang=l("moment.lang is deprecated. Use moment.locale instead.",function(t,e){return Ce.locale(t,e)}),Ce.locale=function(t,e){var i;return t&&(i="undefined"!=typeof e?Ce.defineLocale(t,e):Ce.localeData(t),i&&(Ce.duration._locale=Ce._locale=i)),Ce._locale._abbr},Ce.defineLocale=function(t,e){return null!==e?(e.abbr=t,He[t]||(He[t]=new g),He[t].set(e),Ce.locale(t),He[t]):(delete He[t],null)},Ce.langData=l("moment.langData is deprecated. Use moment.localeData instead.",function(t){return Ce.localeData(t)}),Ce.localeData=function(t){var e;if(t&&t._locale&&t._locale._abbr&&(t=t._locale._abbr),!t)return Ce._locale;if(!O(t)){if(e=W(t))return e;t=[t]}return Y(t)},Ce.isMoment=function(t){return t instanceof v||null!=t&&a(t,"_isAMomentObject")},Ce.isDuration=function(t){return t instanceof y};for(Te=Mi.length-1;Te>=0;--Te)L(Mi[Te]);Ce.normalizeUnits=function(t){return E(t)},Ce.invalid=function(t){var e=Ce.utc(0/0);return null!=t?b(e._pf,t):e._pf.userInvalidated=!0,e},Ce.parseZone=function(){return Ce.apply(null,arguments).parseZone()},Ce.parseTwoDigitYear=function(t){return I(t)+(I(t)>68?1900:2e3)},Ce.isDate=T,b(Ce.fn=v.prototype,{clone:function(){return Ce(this)},valueOf:function(){return+this._d-6e4*(this._offset||0)},unix:function(){return Math.floor(+this/1e3)},toString:function(){return this.clone().locale("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=Ce(this).utc();return 00:!1},parsingFlags:function(){return b({},this._pf)},invalidAt:function(){return this._pf.overflow},utc:function(t){return this.utcOffset(0,t)},local:function(t){return this._isUTC&&(this.utcOffset(0,t),this._isUTC=!1,t&&this.subtract(this._dateUtcOffset(),"m")),this},format:function(t){var e=U(this,t||Ce.defaultFormat);return this.localeData().postformat(e)},add:S(1,"add"),subtract:S(-1,"subtract"),diff:function(t,e,i){var s,o,n=G(t,this),r=6e4*(n.utcOffset()-this.utcOffset());return e=E(e),"year"===e||"month"===e||"quarter"===e?(o=m(this,n),"quarter"===e?o/=3:"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:x(o)},from:function(t,e){return Ce.duration({to:this,from:t}).locale(this.locale()).humanize(!e)},fromNow:function(t){return this.from(Ce(),t)},calendar:function(t){var e=t||Ce(),i=G(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.localeData().calendar(o,this,Ce(e)))},isLeapYear:function(){return R(this.year())},isDST:function(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},day:function(t){var e=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=t?(t=ce(t,this.localeData()),this.add(t-e,"d")):e},month:xe("Month",!0),startOf:function(t){switch(t=E(t)){case"year":this.month(0);case"quarter":case"month":this.date(1);case"week":case"isoWeek":case"day":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return"week"===t?this.weekday(0):"isoWeek"===t&&this.isoWeekday(1),"quarter"===t&&this.month(3*Math.floor(this.month()/3)),this},endOf:function(t){return t=E(t),t===n||"millisecond"===t?this:this.startOf(t).add(1,"isoWeek"===t?"week":t).subtract(1,"ms")},isAfter:function(t,e){var i;return e=E("undefined"!=typeof e?e:"millisecond"),"millisecond"===e?(t=Ce.isMoment(t)?t:Ce(t),+this>+t):(i=Ce.isMoment(t)?+t:+Ce(t),i<+this.clone().startOf(e))},isBefore:function(t,e){var i;return e=E("undefined"!=typeof e?e:"millisecond"),"millisecond"===e?(t=Ce.isMoment(t)?t:Ce(t),+t>+this):(i=Ce.isMoment(t)?+t:+Ce(t),+this.clone().endOf(e)t?this:t}),max:l("moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548",function(t){return t=Ce.apply(null,arguments),t>this?this:t}),zone:l("moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779",function(t,e){return null!=t?("string"!=typeof t&&(t=-t),this.utcOffset(t,e),this):-this.utcOffset()}),utcOffset:function(t,e){var i,s=this._offset||0;return null!=t?("string"==typeof t&&(t=Z(t)),Math.abs(t)<16&&(t=60*t),!this._isUTC&&e&&(i=this._dateUtcOffset()),this._offset=t,this._isUTC=!0,null!=i&&this.add(i,"m"),s!==t&&(!e||this._changeInProgress?C(this,Ce.duration(t-s,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,Ce.updateOffset(this,!0),this._changeInProgress=null)),this):this._isUTC?s:this._dateUtcOffset()},isLocal:function(){return!this._isUTC},isUtcOffset:function(){return this._isUTC},isUtc:function(){return this._isUTC&&0===this._offset},zoneAbbr:function(){return this._isUTC?"UTC":""},zoneName:function(){return this._isUTC?"Coordinated Universal Time":""},parseZone:function(){return this._tzm?this.utcOffset(this._tzm):"string"==typeof this._i&&this.utcOffset(Z(this._i)),this},hasAlignedHourOffset:function(t){return t=t?Ce(t).utcOffset():0,(this.utcOffset()-t)%60===0},daysInMonth:function(){return z(this.year(),this.month())},dayOfYear:function(t){var e=Ne((Ce(this).startOf("day")-Ce(this).startOf("year"))/864e5)+1;return null==t?e:this.add(t-e,"d")},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=me(this,this.localeData()._week.dow,this.localeData()._week.doy).year;return null==t?e:this.add(t-e,"y")},isoWeekYear:function(t){var e=me(this,1,4).year;return null==t?e:this.add(t-e,"y")},week:function(t){var e=this.localeData().week(this);return null==t?e:this.add(7*(t-e),"d")},isoWeek:function(t){var e=me(this,1,4).week;return null==t?e:this.add(7*(t-e),"d")},weekday:function(t){var e=(this.day()+7-this.localeData()._week.dow)%7;return null==t?e:this.add(t-e,"d")},isoWeekday:function(t){return null==t?this.day()||7:this.day(this.day()%7?t:t-7)},isoWeeksInYear:function(){return A(this.year(),1,4)},weeksInYear:function(){var t=this.localeData()._week;return A(this.year(),t.dow,t.doy)},get:function(t){return t=E(t),this[t]()},set:function(t,e){var i;if("object"==typeof t)for(i in t)this.set(i,t[i]);else t=E(t),"function"==typeof this[t]&&this[t](e);return this},locale:function(t){var e;return t===n?this._locale._abbr:(e=Ce.localeData(t),null!=e&&(this._locale=e),this)},lang:l("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(t){return t===n?this.localeData():this.locale(t)}),localeData:function(){return this._locale},_dateUtcOffset:function(){return 15*-Math.round(this._d.getTimezoneOffset()/15)}}),Ce.fn.millisecond=Ce.fn.milliseconds=xe("Milliseconds",!1),Ce.fn.second=Ce.fn.seconds=xe("Seconds",!1),Ce.fn.minute=Ce.fn.minutes=xe("Minutes",!1),Ce.fn.hour=Ce.fn.hours=xe("Hours",!0),Ce.fn.date=xe("Date",!0),Ce.fn.dates=l("dates accessor is deprecated. Use date instead.",xe("Date",!0)),Ce.fn.year=xe("FullYear",!0),Ce.fn.years=l("years accessor is deprecated. Use year instead.",xe("FullYear",!0)),Ce.fn.days=Ce.fn.day,Ce.fn.months=Ce.fn.month,Ce.fn.weeks=Ce.fn.week,Ce.fn.isoWeeks=Ce.fn.isoWeek,Ce.fn.quarters=Ce.fn.quarter,Ce.fn.toJSON=Ce.fn.toISOString,Ce.fn.isUTC=Ce.fn.isUtc,b(Ce.duration.fn=y.prototype,{_bubble:function(){var t,e,i,s=this._milliseconds,o=this._days,n=this._months,r=this._data,a=0;r.milliseconds=s%1e3,t=x(s/1e3),r.seconds=t%60,e=x(t/60),r.minutes=e%60,i=x(e/60),r.hours=i%24,o+=x(i/24),a=x(we(o)),o-=x(De(a)),n+=x(o/30),o%=30,a+=x(n/12),n%=12,r.days=o,r.months=n,r.years=a},abs:function(){return this._milliseconds=Math.abs(this._milliseconds),this._days=Math.abs(this._days),this._months=Math.abs(this._months),this._data.milliseconds=Math.abs(this._data.milliseconds),this._data.seconds=Math.abs(this._data.seconds),this._data.minutes=Math.abs(this._data.minutes),this._data.hours=Math.abs(this._data.hours),this._data.months=Math.abs(this._data.months),this._data.years=Math.abs(this._data.years),this},weeks:function(){return x(this.days()/7)},valueOf:function(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*I(this._months/12)},humanize:function(t){var e=ue(this,!t,this.localeData());return t&&(e=this.localeData().pastFuture(+this,e)),this.localeData().postformat(e)},add:function(t,e){var i=Ce.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=Ce.duration(t,e);return this._milliseconds-=i._milliseconds,this._days-=i._days,this._months-=i._months,this._bubble(),this},get:function(t){return t=E(t),this[t.toLowerCase()+"s"]()},as:function(t){var e,i;if(t=E(t),"month"===t||"year"===t)return e=this._days+this._milliseconds/864e5,i=this._months+12*we(e),"month"===t?i:i/12;switch(e=this._days+Math.round(De(this._months/12)),t){case"week":return e/7+this._milliseconds/6048e5;case"day":return e+this._milliseconds/864e5;case"hour":return 24*e+this._milliseconds/36e5;case"minute":return 24*e*60+this._milliseconds/6e4;case"second":return 24*e*60*60+this._milliseconds/1e3;case"millisecond":return Math.floor(24*e*60*60*1e3)+this._milliseconds;default:throw new Error("Unknown unit "+t)}},lang:Ce.fn.lang,locale:Ce.fn.locale,toIsoString:l("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",function(){return this.toISOString()}),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"},localeData:function(){return this._locale},toJSON:function(){return this.toISOString()}}),Ce.duration.fn.toString=Ce.duration.fn.toISOString;for(Te in fi)a(fi,Te)&&Me(Te.toLowerCase());Ce.duration.fn.asMilliseconds=function(){return this.as("ms")},Ce.duration.fn.asSeconds=function(){return this.as("s")},Ce.duration.fn.asMinutes=function(){return this.as("m")},Ce.duration.fn.asHours=function(){return this.as("h")},Ce.duration.fn.asDays=function(){return this.as("d")},Ce.duration.fn.asWeeks=function(){return this.as("weeks")},Ce.duration.fn.asMonths=function(){return this.as("M")},Ce.duration.fn.asYears=function(){return this.as("y")},Ce.locale("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(t){var e=t%10,i=1===I(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th";return t+i}}),We?o.exports=Ce:(s=function(t,e,i){return i.config&&i.config()&&i.config().noGlobal===!0&&(Ee.moment=Oe),Ce}.call(e,i,e,o),!(s!==n&&(o.exports=s)),Se(!0))}).call(this)}).call(e,function(){return this}(),i(5)(t))},function(t){function e(t){throw new Error("Cannot find module '"+t+"'.")}e.keys=function(){return[]},e.resolve=e,t.exports=e,e.id=4},function(t){t.exports=function(t){return t.webpackPolyfill||(t.deprecate=function(){},t.paths=[],t.children=[],t.webpackPolyfill=1),t}},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,s){var o;return e.hasOwnProperty(t)?e[t].redundant.length>0?(o=e[t].redundant[0],e[t].redundant.shift()):(o=document.createElement(t),void 0!==s?i.insertBefore(o,s):i.appendChild(o)):(o=document.createElement(t),e[t]={used:[],redundant:[]},void 0!==s?i.insertBefore(o,s):i.appendChild(o)),e[t].used.push(o),o},e.drawPoint=function(t,i,s,o,n,r){var a;"circle"==s.options.drawPoints.style?(a=e.getSVGElement("circle",o,n),a.setAttributeNS(null,"cx",t),a.setAttributeNS(null,"cy",i),a.setAttributeNS(null,"r",.5*s.options.drawPoints.size)):(a=e.getSVGElement("rect",o,n),a.setAttributeNS(null,"x",t-.5*s.options.drawPoints.size),a.setAttributeNS(null,"y",i-.5*s.options.drawPoints.size),a.setAttributeNS(null,"width",s.options.drawPoints.size),a.setAttributeNS(null,"height",s.options.drawPoints.size)),void 0!==s.options.drawPoints.styles&&a.setAttributeNS(null,"style",s.group.options.drawPoints.styles),a.setAttributeNS(null,"class",s.className+" point");var h=e.getSVGElement("text",o,n);return r&&(r.xOffset&&(t+=r.xOffset),r.yOffset&&(i+=r.yOffset),r.content&&(h.textContent=r.content),r.className&&h.setAttributeNS(null,"class",r.className+" label")),h.setAttributeNS(null,"x",t),h.setAttributeNS(null,"y",i),a},e.drawBar=function(t,i,s,o,n,r,a){if(0!=o){0>o&&(o*=-1,i-=o);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.length=0,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),this.setOptions(e)}var o=i(1),n=i(8);s.prototype.setOptions=function(t){t&&void 0!==t.queue&&(t.queue===!1?this._queue&&(this._queue.destroy(),delete this._queue):(this._queue||(this._queue=n.extend(this,{replace:["add","update","remove"]})),"object"==typeof t.queue&&this._queue.setOptions(t.queue)))},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=[],r=this,a=r._fieldId,h=function(t){var e=t[a];r._data[e]?(e=r._updateItem(t),s.push(e),n.push(t)):(e=r._addItem(t),i.push(e))};if(Array.isArray(t))for(var d=0,l=t.length;l>d;d++)h(t[d]);else if(o.isDataTable(t))for(var c=this._getColumnNames(t),p=0,u=t.getNumberOfRows();u>p;p++){for(var m={},f=0,g=c.length;g>f;f++){var v=c[f];m[v]=t.getValue(p,f)}h(m)}else{if(!(t instanceof Object))throw new Error("Unknown dataType");h(t)}return i.length&&this._trigger("add",{items:i},e),s.length&&this._trigger("update",{items:s,data:n},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,f=[];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))&&f.push(d);else for(l in this._data)this._data.hasOwnProperty(l)&&(d=n._getItem(l,u),(!m||m(d))&&f.push(d));if(i&&i.order&&void 0==t&&this._sort(f,i.order),i&&i.fields){var g=i.fields;if(void 0!=t)d=this._filterFields(d,g);else for(c=0,p=f.length;p>c;c++)f[c]=this._filterFields(f[c],g)}if("DataTable"==a){var v=this._getColumnNames(s);if(void 0!=t)n._appendRow(s,v,d);else for(c=0;cc;c++)s.push(f[c]);return s}return f},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){if(!t)return t;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],this.length--,t}else if(t instanceof Object){var e=t[this._fieldId];if(e&&this._data[e])return delete this._data[e],this.length--,e}return null},s.prototype.clear=function(t){var e=Object.keys(this._data);return this._data={},this.length=0,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){function e(t){this.delay=null,this.max=1/0,this._queue=[],this._timeout=null,this._extended=null,this.setOptions(t)}e.prototype.setOptions=function(t){t&&"undefined"!=typeof t.delay&&(this.delay=t.delay),t&&"undefined"!=typeof t.max&&(this.max=t.max),this._flushIfNeeded()},e.extend=function(t,i){var s=new e(i);if(void 0!==t.flush)throw new Error("Target object already has a property flush");t.flush=function(){s.flush()};var o=[{name:"flush",original:void 0}];if(i&&i.replace)for(var n=0;nthis.max&&this.flush(),clearTimeout(this._timeout),this.queue.length>0&&"number"==typeof this.delay){var t=this;this._timeout=setTimeout(function(){t.flush()},this.delay)}},e.prototype.flush=function(){for(;this._queue.length>0;){var t=this._queue.shift();t.fn.apply(t.context||t.fn,t.args||[])}},t.exports=e},function(t,e,i){function s(t,e){this._data=null,this._ids={},this.length=0,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(7);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.length=0,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.length=e.length,this._trigger("add",{items:e}),this._data.on&&this._data.on("*",this.listener)}},s.prototype.refresh=function(){for(var t,e=this._data.getIds({filter:this._options&&this._options.filter}),i={},s=[],o=[],n=0;ns;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))}this.length+=d.length-c.length,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";var o=function(t){return t};this.xValueLabel=o,this.yValueLabel=o,this.zValueLabel=o,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 p,this.eye=new l(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)}function o(t){return"clientX"in t?t.clientX:t.targetTouches[0]&&t.targetTouches[0].clientX||0}function n(t){return"clientY"in t?t.clientY:t.targetTouches[0]&&t.targetTouches[0].clientY||0}var r=i(11),a=i(7),h=i(9),d=i(1),l=i(12),c=i(13),p=i(14),u=i(15),m=i(16),f=i(17);r(s.prototype),s.prototype._setScale=function(){this.scale=new l(1/(this.xMax-this.xMin),1/(this.yMax-this.yMin),1/(this.zMax-this.zMin)),this.keepAspectRatio&&(this.scale.x3&&(this.colFilter=3);else{if(this.style!==s.STYLE.DOTCOLOR&&this.style!==s.STYLE.DOTSIZE&&this.style!==s.STYLE.BARCOLOR&&this.style!==s.STYLE.BARSIZE)throw'Unknown style "'+this.style+'"';this.colX=0,this.colY=1,this.colZ=2,this.colValue=3,t.getNumberOfColumns()>4&&(this.colFilter=4)}},s.prototype.getNumberOfRows=function(t){return t.length},s.prototype.getNumberOfColumns=function(t){var e=0;for(var i in t[0])t[0].hasOwnProperty(i)&&e++;return e},s.prototype.getDistinctValues=function(t,e){for(var i=[],s=0;st[s][e]&&(i.min=t[s][e]),i.maxt;t++){var m=(t-p)/(u-p),g=240*m,v=this._hsv2rgb(g,1,1);c.strokeStyle=v,c.beginPath(),c.moveTo(h,r+t),c.lineTo(a,r+t),c.stroke()}c.strokeStyle=this.colorAxis,c.strokeRect(h,r,i,n)}if(this.style===s.STYLE.DOTSIZE&&(c.strokeStyle=this.colorAxis,c.fillStyle=this.colorDot,c.beginPath(),c.moveTo(h,r),c.lineTo(a,r),c.lineTo(a-i+e,d),c.lineTo(h,d),c.closePath(),c.fill(),c.stroke()),this.style===s.STYLE.DOTCOLOR||this.style===s.STYLE.DOTSIZE){var y=5,b=new f(this.valueMin,this.valueMax,(this.valueMax-this.valueMin)/5,!0);for(b.start(),b.getCurrent()0?this.yMin:this.yMax,o=this._convert3Dto2D(new l(x,r,this.zMin)),Math.cos(2*_)>0?(g.textAlign="center",g.textBaseline="top",o.y+=b):Math.sin(2*_)<0?(g.textAlign="right",g.textBaseline="middle"):(g.textAlign="left",g.textBaseline="middle"),g.fillStyle=this.colorAxis,g.fillText(" "+this.xValueLabel(i.getCurrent())+" ",o.x,o.y),i.next()}for(g.lineWidth=1,s=void 0===this.defaultYStep,i=new f(this.yMin,this.yMax,this.yStep,s),i.start(),i.getCurrent()0?this.xMin:this.xMax,o=this._convert3Dto2D(new l(n,i.getCurrent(),this.zMin)),Math.cos(2*_)<0?(g.textAlign="center",g.textBaseline="top",o.y+=b):Math.sin(2*_)>0?(g.textAlign="right",g.textBaseline="middle"):(g.textAlign="left",g.textBaseline="middle"),g.fillStyle=this.colorAxis,g.fillText(" "+this.yValueLabel(i.getCurrent())+" ",o.x,o.y),i.next();for(g.lineWidth=1,s=void 0===this.defaultZStep,i=new f(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 l(n,r,i.getCurrent())),g.strokeStyle=this.colorAxis,g.beginPath(),g.moveTo(t.x,t.y),g.lineTo(t.x-b,t.y),g.stroke(),g.textAlign="right",g.textBaseline="middle",g.fillStyle=this.colorAxis,g.fillText(this.zValueLabel(i.getCurrent())+" ",t.x-5,t.y),i.next();g.lineWidth=1,t=this._convert3Dto2D(new l(n,r,this.zMin)),e=this._convert3Dto2D(new l(n,r,this.zMax)),g.strokeStyle=this.colorAxis,g.beginPath(),g.moveTo(t.x,t.y),g.lineTo(e.x,e.y),g.stroke(),g.lineWidth=1,p=this._convert3Dto2D(new l(this.xMin,this.yMin,this.zMin)),u=this._convert3Dto2D(new l(this.xMax,this.yMin,this.zMin)),g.strokeStyle=this.colorAxis,g.beginPath(),g.moveTo(p.x,p.y),g.lineTo(u.x,u.y),g.stroke(),p=this._convert3Dto2D(new l(this.xMin,this.yMax,this.zMin)),u=this._convert3Dto2D(new l(this.xMax,this.yMax,this.zMin)),g.strokeStyle=this.colorAxis,g.beginPath(),g.moveTo(p.x,p.y),g.lineTo(u.x,u.y),g.stroke(),g.lineWidth=1,t=this._convert3Dto2D(new l(this.xMin,this.yMin,this.zMin)),e=this._convert3Dto2D(new l(this.xMin,this.yMax,this.zMin)),g.strokeStyle=this.colorAxis,g.beginPath(),g.moveTo(t.x,t.y),g.lineTo(e.x,e.y),g.stroke(),t=this._convert3Dto2D(new l(this.xMax,this.yMin,this.zMin)),e=this._convert3Dto2D(new l(this.xMax,this.yMax,this.zMin)),g.strokeStyle=this.colorAxis,g.beginPath(),g.moveTo(t.x,t.y),g.lineTo(e.x,e.y),g.stroke();var w=this.xLabel;w.length>0&&(c=.1/this.scale.y,n=(this.xMin+this.xMax)/2,r=Math.cos(_)>0?this.yMin-c:this.yMax+c,o=this._convert3Dto2D(new l(n,r,this.zMin)),Math.cos(2*_)>0?(g.textAlign="center",g.textBaseline="top"):Math.sin(2*_)<0?(g.textAlign="right",g.textBaseline="middle"):(g.textAlign="left",g.textBaseline="middle"),g.fillStyle=this.colorAxis,g.fillText(w,o.x,o.y));var D=this.yLabel;D.length>0&&(d=.1/this.scale.x,n=Math.sin(_)>0?this.xMin-d:this.xMax+d,r=(this.yMin+this.yMax)/2,o=this._convert3Dto2D(new l(n,r,this.zMin)),Math.cos(2*_)<0?(g.textAlign="center",g.textBaseline="top"):Math.sin(2*_)>0?(g.textAlign="right",g.textBaseline="middle"):(g.textAlign="left",g.textBaseline="middle"),g.fillStyle=this.colorAxis,g.fillText(D,o.x,o.y));var M=this.zLabel;M.length>0&&(h=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 l(n,r,a)),g.textAlign="right",g.textBaseline="middle",g.fillStyle=this.colorAxis,g.fillText(M,o.x-h,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,h,d,c,p,u,m,f=this.frame.canvas,g=f.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+D.x/M/2,1),a=this._hsv2rgb(c,p,u),h=a):(u=1,a=this._hsv2rgb(c,p,u),h=this.colorAxis)):(a="gray",h=this.colorAxis),d=.5,g.lineWidth=d,g.fillStyle=a,g.strokeStyle=h,g.beginPath(),g.moveTo(t.screen.x,t.screen.y),g.lineTo(e.screen.x,e.screen.y),g.lineTo(o.screen.x,o.screen.y),g.lineTo(i.screen.x,i.screen.y),g.closePath(),g.fill(),g.stroke()}}else for(n=0;np&&(p=0);var u,m,f;this.style===s.STYLE.DOTCOLOR?(u=240*(1-(d.point.value-this.valueMin)*this.scale.value),m=this._hsv2rgb(u,1,1),f=this._hsv2rgb(u,1,.8)):this.style===s.STYLE.DOTSIZE?(m=this.colorDot,f=this.colorDotBorder):(u=240*(1-(d.point.z-this.zMin)*this.scale.z/this.verticalRatio),m=this._hsv2rgb(u,1,1),f=this._hsv2rgb(u,1,.8)),i.lineWidth=1,i.strokeStyle=f,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=o(t),this.startMouseY=n(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)},d.addEventListener(document,"mousemove",e.onmousemove),d.addEventListener(document,"mouseup",e.onmouseup),d.preventDefault(t)}},s.prototype._onMouseMove=function(t){t=t||window.event;var e=parseFloat(o(t))-this.startMouseX,i=parseFloat(n(t))-this.startMouseY,s=this.startArmRotation.horizontal+e/200,r=this.startArmRotation.vertical+i/200,a=4,h=Math.sin(a/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 c(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 d=n.surfaces;if(d)for(var l=d.length-1;l>=0;l--){var p=d[l],u=p.corners,m=[u[0].screen,u[1].screen,u[2].screen],f=[u[2].screen,u[3].screen,u[0].screen];if(this._insideTriangle(h,m)||this._insideTriangle(h,f))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)}}},t.exports=s},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){this.x=void 0!==t?t:0,this.y=void 0!==e?e:0,this.z=void 0!==i?i:0}e.subtract=function(t,i){var s=new e;return s.x=t.x-i.x,s.y=t.y-i.y,s.z=t.z-i.z,s},e.add=function(t,i){var s=new e;return s.x=t.x+i.x,s.y=t.y+i.y,s.z=t.z+i.z,s},e.avg=function(t,i){return new e((t.x+i.x)/2,(t.y+i.y)/2,(t.z+i.z)/2)},e.crossProduct=function(t,i){var s=new e;return s.x=t.y*i.z-t.z*i.y,s.y=t.z*i.x-t.x*i.z,s.z=t.x*i.y-t.y*i.x,s},e.prototype.length=function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)},t.exports=e},function(t){function e(t,e){this.x=void 0!==t?t:0,this.y=void 0!==e?e:0}t.exports=e},function(t,e,i){function s(){this.armLocation=new o,this.armRotation={},this.armRotation.horizontal=0,this.armRotation.vertical=0,this.armLength=1.7,this.cameraLocation=new o,this.cameraRotation=new o(.5*Math.PI,0,0),this.calculateCameraOrientation()}var o=i(12);s.prototype.setArmLocation=function(t,e,i){this.armLocation.x=t,this.armLocation.y=e,this.armLocation.z=i,this.calculateCameraOrientation()},s.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()},s.prototype.getArmRotation=function(){var t={};return t.horizontal=this.armRotation.horizontal,t.vertical=this.armRotation.vertical,t},s.prototype.setArmLength=function(t){void 0!==t&&(this.armLength=t,this.armLength<.71&&(this.armLength=.71),this.armLength>5&&(this.armLength=5),this.calculateCameraOrientation())},s.prototype.getArmLength=function(){return this.armLength},s.prototype.getCameraLocation=function(){return this.cameraLocation},s.prototype.getCameraRotation=function(){return this.cameraRotation},s.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=s},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(9);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,h){if(!(this instanceof s))throw new SyntaxError("Constructor must be called with the new operator");if(!(Array.isArray(i)||i instanceof n||i instanceof r)&&i instanceof Object){var u=h;h=i,i=u}var m=this;this.defaultOptions={start:null,end:null,autoResize:!0,orientation:"bottom",width:null,height:null,maxHeight:null,minHeight:null},this.options=o.deepExtend({},this.defaultOptions),this._create(t),this.components=[],this.body={dom:this.dom,domProps:this.props,emitter:{on:this.on.bind(this),off:this.off.bind(this),emit:this.emit.bind(this)},hiddenDates:[],util:{getScale:function(){return m.timeAxis.step.scale},getStep:function(){return m.timeAxis.step.step},toScreen:m._toScreen.bind(m),toGlobalScreen:m._toGlobalScreen.bind(m),toTime:m._toTime.bind(m),toGlobalTime:m._toGlobalTime.bind(m)}},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.currentTime=new l(this.body),this.components.push(this.currentTime),this.customTime=new c(this.body),this.components.push(this.customTime),this.itemSet=new p(this.body),this.components.push(this.itemSet),this.itemsData=null,this.groupsData=null,h&&this.setOptions(h),i&&this.setGroups(i),e?this.setItems(e):this._redraw()}var o=(i(11),i(19),i(1)),n=i(7),r=i(9),a=i(21),h=i(25),d=i(38),l=i(39),c=i(41),p=i(26);s.prototype=new h,s.prototype.redraw=function(){this.itemSet&&this.itemSet.markDirty({refreshItems:!0}),this._redraw()},s.prototype.setItems=function(t){var e,i=null==this.itemsData;if(e=t?t instanceof n||t instanceof r?t:new n(t,{type:{start:"Date",end:"Date"}}):null,this.itemsData=e,this.itemSet&&this.itemSet.setItems(e),i)if(void 0!=this.options.start||void 0!=this.options.end){if(void 0==this.options.start||void 0==this.options.end)var s=this._getDataRange();var o=void 0!=this.options.start?this.options.start:s.start,a=void 0!=this.options.end?this.options.end:s.end;this.setWindow(o,a,{animate:!1})}else this.fit({animate:!1})},s.prototype.setGroups=function(t){var e;e=t?t instanceof n||t instanceof r?t:new n(t):null,this.groupsData=e,this.itemSet.setGroups(e)},s.prototype.setSelection=function(t,e){this.itemSet&&this.itemSet.setSelection(t),e&&e.focus&&this.focus(t,e)},s.prototype.getSelection=function(){return this.itemSet&&this.itemSet.getSelection()||[]},s.prototype.focus=function(t,e){if(this.itemsData&&void 0!=t){var i=Array.isArray(t)?t:[t],s=this.itemsData.getDataSet().get(i,{type:{start:"Date",end:"Date"}}),o=null,n=null;if(s.forEach(function(t){var e=t.start.valueOf(),i="end"in t?t.end.valueOf():t.start.valueOf();(null===o||o>e)&&(o=e),(null===n||i>n)&&(n=i)}),null!==o&&null!==n){var r=(o+n)/2,a=Math.max(this.range.end-this.range.start,1.1*(n-o)),h=e&&void 0!==e.animate?e.animate:!0;this.range.setRange(r-a/2,r+a/2,h)}}},s.prototype.getItemRange=function(){var t=this.itemsData.getDataSet(),e=null,i=null;if(t){var s=t.min("start");e=s?o.convert(s.start,"Date").valueOf():null;var n=t.max("start");n&&(i=o.convert(n.start,"Date").valueOf());var r=t.max("end");r&&(i=null==i?o.convert(r.end,"Date").valueOf():Math.max(i,o.convert(r.end,"Date").valueOf()))}return{min:null!=e?new Date(e):null,max:null!=i?new Date(i):null}},t.exports=s},function(t,e,i){t.exports="undefined"!=typeof window?window.Hammer||i(20):function(){throw Error("hammer.js is only available in a browser, not in node.js.")}},function(t,e,i){var s;!function(o,n){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 S(t,e){return new S.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",f=a.POINTER_PEN="pen",g=a.EVENT_START="start",v=a.EVENT_MOVE="move",y=a.EVENT_END="end",b=a.EVENT_RELEASE="release",_=a.EVENT_TOUCH="touch";a.READY=!1,a.plugins=a.plugins||{},a.gestures=a.gestures||{};var x=a.utils={extend:function(t,e,i){for(var s in e)!e.hasOwnProperty(s)||t[s]!==n&&i||(t[s]=e[s]);return t},on:function(t,e,i){t.addEventListener(e,i,!1)},off:function(t,e,i){t.removeEventListener(e,i,!1)},each:function(t,e,i){var s,o;if("forEach"in t)t.forEach(e,i);else if(t.length!==n){for(s=0,o=t.length;o>s;s++)if(e.call(i,t[s],s,t)===!1)return}else for(s in t)if(t.hasOwnProperty(s)&&e.call(i,t[s],s,t)===!1)return},inStr:function(t,e){return t.indexOf(e)>-1},inArray:function(t,e){if(t.indexOf){var i=t.indexOf(e);return-1===i?!1:i}for(var s=0,o=t.length;o>s;s++)if(t[s]===e)return s;return!1},toArray:function(t){return Array.prototype.slice.call(t,0)},hasParent:function(t,e){for(;t;){if(t==e)return!0;t=t.parentNode}return!1},getCenter:function(t){var e=[],i=[],s=[],o=[],n=Math.min,r=Math.max;return 1===t.length?{pageX:t[0].pageX,pageY:t[0].pageY,clientX:t[0].clientX,clientY:t[0].clientY}:(x.each(t,function(t){e.push(t.pageX),i.push(t.pageY),s.push(t.clientX),o.push(t.clientY)}),{pageX:(n.apply(Math,e)+r.apply(Math,e))/2,pageY:(n.apply(Math,i)+r.apply(Math,i))/2,clientX:(n.apply(Math,s)+r.apply(Math,s))/2,clientY:(n.apply(Math,o)+r.apply(Math,o))/2})},getVelocity:function(t,e,i){return{x:Math.abs(e/t)||0,y:Math.abs(i/t)||0}},getAngle:function(t,e){var i=e.clientX-t.clientX,s=e.clientY-t.clientY;return 180*Math.atan2(s,i)/Math.PI},getDirection:function(t,e){var i=Math.abs(t.clientX-e.clientX),s=Math.abs(t.clientY-e.clientY);return i>=s?t.clientX-e.clientX>0?l:p:t.clientY-e.clientY>0?c:d},getDistance:function(t,e){var i=e.clientX-t.clientX,s=e.clientY-t.clientY;return Math.sqrt(i*i+s*s)},getScale:function(t,e){return t.length>=2&&e.length>=2?this.getDistance(e[0],e[1])/this.getDistance(t[0],t[1]):1},getRotation:function(t,e){return t.length>=2&&e.length>=2?this.getAngle(e[1],e[0])-this.getAngle(t[1],t[0]):0},isVertical:function(t){return t==c||t==d},setPrefixedCss:function(t,e,i,s){var o=["","Webkit","Moz","O","ms"];e=x.toCamelCase(e);for(var n=0;n0&&this.started&&(r=v),this.started=!0;var d=this.collectEventData(i,r,o,t);return e!=y&&s.call(M,d),a&&(d.changedLength=h,d.eventType=a,s.call(M,d),d.eventType=r,delete d.changedLength),r==y&&(s.call(M,d),this.started=!1),r},determineEventTypes:function(){var t;return t=a.HAS_POINTEREVENTS?o.PointerEvent?["pointerdown","pointermove","pointerup pointercancel lostpointercapture"]:["MSPointerDown","MSPointerMove","MSPointerUp MSPointerCancel MSLostPointerCapture"]:a.NO_MOUSEEVENTS?["touchstart","touchmove","touchend touchcancel"]:["touchstart mousedown","touchmove mousemove","touchend touchcancel mouseup"],h[g]=t[0],h[v]=t[1],h[y]=t[2],h},getTouchList:function(t,e){if(a.HAS_POINTEREVENTS)return D.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")||D.matchType(u,s)?o=u:D.matchType(f,s)&&(o=f),{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()}}}},D=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[f]=i===(e.MSPOINTER_TYPE_PEN||f),s[t]},reset:function(){this.pointers={}}},M=a.detection={gestures:[],current:null,previous:null,stopped:!1,startDetect:function(t,e){this.current||(this.stopped=!1,this.current={inst:t,startEvent:x.extend({},e),lastEvent:!1,lastCalcEvent:!1,futureCalcEvent:!1,lastCalcData:{},name:""},this.detect(e))},detect:function(t){if(this.current&&!this.stopped){t=this.extendEventData(t);var e=this.current.inst,i=e.options;return x.each(this.gestures,function(s){!this.stopped&&e.enabled&&i[s.name]&&s.handler.call(s,t,e)},this),this.current&&(this.current.lastEvent=t),t.eventType==y&&this.stopDetect(),t}},stopDetect:function(){this.previous=x.extend({},this.current),this.current=null,this.stopped=!0},getCalculatedData:function(t,e,i,s,o){var n=this.current,r=!1,h=n.lastCalcEvent,d=n.lastCalcData;h&&t.timeStamp-h.timeStamp>a.CALCULATE_INTERVAL&&(e=h.center,i=t.timeStamp-h.timeStamp,s=t.center.clientX-h.center.clientX,o=t.center.clientY-h.center.clientY,r=!0),(t.eventType==_||t.eventType==b)&&(n.futureCalcEvent=t),(!n.lastCalcEvent||r)&&(d.velocity=x.getVelocity(i,s,o),d.angle=x.getAngle(e,t.center),d.direction=x.getDirection(e,t.center),n.lastCalcEvent=n.futureCalcEvent||t,n.futureCalcEvent=t),t.velocityX=d.velocity.x,t.velocityY=d.velocity.y,t.interimAngle=d.angle,t.interimDirection=d.direction},extendEventData:function(t){var e=this.current,i=e.startEvent,s=e.lastEvent||i;(t.eventType==_||t.eventType==b)&&(i.touches=[],x.each(t.touches,function(t){i.touches.push({clientX:t.clientX,clientY:t.clientY})}));var o=t.timeStamp-i.timeStamp,n=t.center.clientX-i.center.clientX,r=t.center.clientY-i.center.clientY;return this.getCalculatedData(t,s.center,o,n,r),x.extend(t,{startEvent:i,deltaTime:o,deltaX:n,deltaY:r,distance:x.getDistance(i.center,t.center),angle:x.getAngle(i.center,t.center),direction:x.getDirection(i.center,t.center),scale:x.getScale(i.touches,t.touches),rotation:x.getRotation(i.touches,t.touches)}),t},register:function(t){var e=t.defaults||{};return e[t.name]===n&&(e[t.name]=!0),x.extend(a.defaults,e,!0),t.index=t.index||1e3,this.gestures.push(t),this.gestures.sort(function(t,e){return t.indexe.index?1:0}),this.gestures}};a.Instance=function(t,e){var i=this;r(),this.element=t,this.enabled=!0,x.each(e,function(t,i){delete e[i],e[x.toCamelCase(i)]=t}),this.options=x.extend(x.extend({},a.defaults),e||{}),this.options.behavior&&x.toggleBehavior(this.element,this.options.behavior,!0),this.eventStartHandler=w.onTouch(t,g,function(t){i.enabled&&t.eventType==g?M.startDetect(i,t):t.eventType==_&&M.detect(t)}),this.eventHandlers=[]},a.Instance.prototype={on:function(t,e){var i=this;return w.on(i.element,t,e,function(t){i.eventHandlers.push({gesture:t,handler:e})}),i},off:function(t,e){var i=this;return w.off(i.element,t,e,function(t){var s=x.inArray({gesture:t,handler:e});s!==!1&&i.eventHandlers.splice(s,1)}),i},trigger:function(t,e){e||(e={});var i=a.DOCUMENT.createEvent("Event");i.initEvent(t,!0,!0),i.gesture=e;var s=this.element;return x.hasParent(e.target,s)&&(s=e.target),s.dispatchEvent(i),this},enable:function(t){return this.enabled=t,this},dispose:function(){var t,e;for(x.toggleBehavior(this.element,this.options.behavior,!1),t=-1;e=this.eventHandlers[++t];)x.off(this.element,e.gesture,e.handler);return this.eventHandlers=[],w.off(this.element,h[g],this.eventStartHandler),null}},function(t){function e(e,s){var o=M.current;if(!(s.options.dragMaxTouches>0&&e.touches.length>s.options.dragMaxTouches))switch(e.eventType){case g:i=!1;break;case v:if(e.distance0)){var r=Math.abs(s.options.dragMinDistance/e.distance);n.pageX+=e.deltaX*r,n.pageY+=e.deltaY*r,n.clientX+=e.deltaX*r,n.clientY+=e.deltaY*r,e=M.extendEventData(e)}(o.lastEvent.dragLockToAxis||s.options.dragLockToAxis&&s.options.dragLockMinDistance<=e.distance)&&(e.dragLockToAxis=!0);var a=o.lastEvent.direction;e.dragLockToAxis&&a!==e.direction&&(e.direction=x.isVertical(a)?e.deltaY<0?c:d:e.deltaX<0?l:p),i||(s.trigger(t+"start",e),i=!0),s.trigger(t,e),s.trigger(t+e.direction,e);var h=x.isVertical(e.direction);(s.options.dragBlockVertical&&h||s.options.dragBlockHorizontal&&!h)&&e.preventDefault();break;case b:i&&e.changedLength<=s.options.dragMaxTouches&&(s.trigger(t+"end",e),i=!1);break;case y:i=!1}}var i=!1;a.gestures.Drag={name:t,index:50,handler:e,defaults:{dragMinDistance:10,dragDistanceCorrection:!0,dragMaxTouches:1,dragBlockHorizontal:!1,dragBlockVertical:!1,dragLockToAxis:!1,dragLockMinDistance:25}}}("drag"),a.gestures.Gesture={name:"gesture",index:1337,handler:function(t,e){e.trigger(this.name,t)}},function(t){function e(e,s){var o=s.options,n=M.current;switch(e.eventType){case g:clearTimeout(i),n.name=t,i=setTimeout(function(){n&&n.name==t&&s.trigger(t,e)},o.holdTimeout);break;case v:e.distance>o.holdThreshold&&clearTimeout(i);break;case b:clearTimeout(i)}}var i;a.gestures.Hold={name:t,index:10,defaults:{holdTimeout:500,holdThreshold:2},handler:e}}("hold"),a.gestures.Release={name:"release",index:1/0,handler:function(t,e){t.eventType==b&&e.trigger(this.name,t)}},a.gestures.Swipe={name:"swipe",index:40,defaults:{swipeMinTouches:1,swipeMaxTouches:1,swipeVelocityX:.6,swipeVelocityY:.6},handler:function(t,e){if(t.eventType==b){var i=t.touches.length,s=e.options;if(is.swipeMaxTouches)return;(t.velocityX>s.swipeVelocityX||t.velocityY>s.swipeVelocityY)&&(e.trigger(this.name,t),e.trigger(this.name+t.direction,t))}}},function(t){function e(e,s){var o,n,r=s.options,a=M.current,h=M.previous;switch(e.eventType){case g:i=!1;break;case v:i=i||e.distance>r.tapMaxDistance;break;case y:!x.inStr(e.srcEvent.type,"cancel")&&e.deltaTimes.options.transformMinRotation&&s.trigger("rotate",e),o>s.options.transformMinScale&&(s.trigger("pinch",e),s.trigger("pinch"+(e.scale<1?"in":"out"),e));break;case b:i&&e.changedLength<2&&(s.trigger(t+"end",e),i=!1)}}var i=!1;a.gestures.Transform={name:t,index:45,defaults:{transformMinScale:.01,transformMinRotation:1},handler:e}}("transform"),s=function(){return a}.call(e,i,e,t),!(s!==n&&(t.exports=s))}(window)},function(t,e,i){function s(t,e){var i=h().hours(0).minutes(0).seconds(0).milliseconds(0);this.start=i.clone().add(-3,"days").valueOf(),this.end=i.clone().add(4,"days").valueOf(),this.body=t,this.deltaDifference=0,this.scaleOffset=0,this.startToFront=!1,this.endToFront=!0,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.animateTimer=null,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(22),h=i(2),d=i(23),l=i(24);s.prototype=new d,s.prototype.setOptions=function(t){if(t){var e=["direction","min","max","zoomMin","zoomMax","moveable","zoomable","activate","hiddenDates"];r.selectiveExtend(e,this.options,t),("start"in t||"end"in t)&&this.setRange(t.start,t.end)}},s.prototype.setRange=function(t,e,i,s){s!==!0&&(s=!1);var o=void 0!=t?r.convert(t,"Date").valueOf():null,n=void 0!=e?r.convert(e,"Date").valueOf():null;if(this._cancelAnimation(),i){var a=this,h=this.start,d=this.end,c="number"==typeof i?i:500,p=(new Date).valueOf(),u=!1,m=function(){if(!a.props.touch.dragging){var t=(new Date).valueOf(),e=t-p,i=e>c,g=i||null===o?o:r.easeInOutQuad(e,h,o,c),v=i||null===n?n:r.easeInOutQuad(e,d,n,c);f=a._applyRange(g,v),l.updateHiddenDates(a.body,a.options.hiddenDates),u=u||f,f&&a.body.emitter.emit("rangechange",{start:new Date(a.start),end:new Date(a.end),byUser:s}),i?u&&a.body.emitter.emit("rangechanged",{start:new Date(a.start),end:new Date(a.end),byUser:s}):a.animateTimer=setTimeout(m,20)}};return m()}var f=this._applyRange(o,n);if(l.updateHiddenDates(this.body,this.options.hiddenDates),f){var g={start:new Date(this.start),end:new Date(this.end),byUser:s};this.body.emitter.emit("rangechange",g),this.body.emitter.emit("rangechanged",g)}},s.prototype._cancelAnimation=function(){this.animateTimer&&(clearTimeout(this.animateTimer),this.animateTimer=null)},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&&od&&(d=0),o-s>d&&(this.end-this.start===d&&sthis.end?(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 s>=this.start&&s<=this.end||o>=this.start&&o<=this.end||this.start>=s&&this.start<=o||this.end>=s&&this.end<=o||this.body.emitter.emit("checkRangedItems"),this.start=s,this.end=o,l},s.prototype.getRange=function(){return{start:this.start,end:this.end} +},s.prototype.conversion=function(t,e){return s.conversion(this.start,this.end,t,e)},s.conversion=function(t,e,i,s){return void 0===s&&(s=0),0!=i&&e-t!=0?{offset:t,scale:i/(e-t-s)}:{offset:0,scale:1}},s.prototype._onDragStart=function(){this.deltaDifference=0,this.previousDelta=0,this.options.moveable&&this.props.touch.allowDragging&&(this.props.touch.start=this.start,this.props.touch.end=this.end,this.props.touch.dragging=!0,this.body.dom.root&&(this.body.dom.root.style.cursor="move"))},s.prototype._onDrag=function(t){if(this.options.moveable&&this.props.touch.allowDragging){var e=this.options.direction;o(e);var i="horizontal"==e?t.gesture.deltaX:t.gesture.deltaY;i-=this.deltaDifference;var s=this.props.touch.end-this.props.touch.start,n=l.getHiddenDurationBetween(this.body.hiddenDates,this.start,this.end);s-=n;var r="horizontal"==e?this.body.domProps.center.width:this.body.domProps.center.height,a=-i/r*s,h=this.props.touch.start+a,d=this.props.touch.end+a,c=l.snapAwayFromHidden(this.body.hiddenDates,h,this.previousDelta-i,!0),p=l.snapAwayFromHidden(this.body.hiddenDates,d,this.previousDelta-i,!0);if(c!=h||p!=d)return this.deltaDifference+=i,this.props.touch.start=c,this.props.touch.end=p,void this._onDrag(t);this.previousDelta=i,this._applyRange(h,d),this.body.emitter.emit("rangechange",{start:new Date(this.start),end:new Date(this.end),byUser:!0})}},s.prototype._onDragEnd=function(){this.options.moveable&&this.props.touch.allowDragging&&(this.props.touch.dragging=!1,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),byUser:!0}))},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,e)}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,this.scaleOffset=0,this.deltaDifference=0},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+this.scaleOffset),i=this._pointerToDate(this.props.touch.center),s=l.getHiddenDurationBetween(this.body.hiddenDates,this.start,this.end),o=l.getHiddenDurationBefore(this.body.hiddenDates,this,i),r=s-o,a=i-o+(this.props.touch.start-(i-o))*e,h=i+r+(this.props.touch.end-(i+r))*e;this.startToFront=1-e>0?!1:!0,this.endToFront=e-1>0?!1:!0;var d=l.snapAwayFromHidden(this.body.hiddenDates,a,1-e,!0),c=l.snapAwayFromHidden(this.body.hiddenDates,h,e-1,!0);(d!=a||c!=h)&&(this.props.touch.start=d,this.props.touch.end=c,this.scaleOffset=1-t.gesture.scale,a=d,h=c),this.setRange(a,h,!1,!0),this.startToFront=!1,this.endToFront=!0}},s.prototype._pointerToDate=function(t){var e,i=this.options.direction;if(o(i),"horizontal"==i)return this.body.util.toTime(t.x).valueOf();var s=this.body.domProps.center.height;return e=this.conversion(s),t.y/e.scale+e.offset},s.prototype.zoom=function(t,e,i){null==e&&(e=(this.start+this.end)/2);var s=l.getHiddenDurationBetween(this.body.hiddenDates,this.start,this.end),o=l.getHiddenDurationBefore(this.body.hiddenDates,this,e),n=s-o,r=e-o+(this.start-(e-o))*t,a=e+n+(this.end-(e+n))*t;this.startToFront=i>0?!1:!0,this.endToFront=-i>0?!1:!0;var h=l.snapAwayFromHidden(this.body.hiddenDates,r,i,!0),d=l.snapAwayFromHidden(this.body.hiddenDates,a,-i,!0);(h!=r||d!=a)&&(r=h,a=d),this.setRange(r,a,!1,!0),this.startToFront=!1,this.endToFront=!0},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,i){var s=i(19);e.fakeGesture=function(t,e){var i=null,o=s.event.getTouchList(e,i),n=s.event.collectEventData(this,i,o,e);return isNaN(n.center.pageX)&&(n.center.pageX=e.pageX),isNaN(n.center.pageY)&&(n.center.pageY=e.pageY),n}},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){var s=i(2);e.convertHiddenOptions=function(t,e){if(t.hiddenDates=[],e&&1==Array.isArray(e)){for(var i=0;i=4*a){var p=0,u=n.clone();switch(i[h].repeat){case"daily":d.day()!=l.day()&&(p=1),d.dayOfYear(o.dayOfYear()),d.year(o.year()),d.subtract(7,"days"),l.dayOfYear(o.dayOfYear()),l.year(o.year()),l.subtract(7-p,"days"),u.add(1,"weeks");break;case"weekly":var m=l.diff(d,"days"),f=d.day();d.date(o.date()),d.month(o.month()),d.year(o.year()),l=d.clone(),d.day(f),l.day(f),l.add(m,"days"),d.subtract(1,"weeks"),l.subtract(1,"weeks"),u.add(1,"weeks");break;case"monthly":d.month()!=l.month()&&(p=1),d.month(o.month()),d.year(o.year()),d.subtract(1,"months"),l.month(o.month()),l.year(o.year()),l.subtract(1,"months"),l.add(p,"months"),u.add(1,"months");break;case"yearly":d.year()!=l.year()&&(p=1),d.year(o.year()),d.subtract(1,"years"),l.year(o.year()),l.subtract(1,"years"),l.add(p,"years"),u.add(1,"years");break;default:return void console.log("Wrong repeat format, allowed are: daily, weekly, monthly, yearly. Given:",i[h].repeat)}for(;u>d;)switch(t.hiddenDates.push({start:d.valueOf(),end:l.valueOf()}),i[h].repeat){case"daily":d.add(1,"days"),l.add(1,"days");break;case"weekly":d.add(1,"weeks"),l.add(1,"weeks");break;case"monthly":d.add(1,"months"),l.add(1,"months");break;case"yearly":d.add(1,"y"),l.add(1,"y");break;default:return void console.log("Wrong repeat format, allowed are: daily, weekly, monthly, yearly. Given:",i[h].repeat)}t.hiddenDates.push({start:d.valueOf(),end:l.valueOf()})}}e.removeDuplicates(t);var g=e.isHidden(t.range.start,t.hiddenDates),v=e.isHidden(t.range.end,t.hiddenDates),y=t.range.start,b=t.range.end;1==g.hidden&&(y=1==t.range.startToFront?g.startDate-1:g.endDate+1),1==v.hidden&&(b=1==t.range.endToFront?v.startDate-1:v.endDate+1),(1==g.hidden||1==v.hidden)&&t.range._applyRange(y,b)}},e.removeDuplicates=function(t){for(var e=t.hiddenDates,i=[],s=0;s=e[s].start&&e[o].end<=e[s].end?e[o].remove=!0:e[o].start>=e[s].start&&e[o].start<=e[s].end?(e[s].end=e[o].end,e[o].remove=!0):e[o].end>=e[s].start&&e[o].end<=e[s].end&&(e[s].start=e[o].start,e[o].remove=!0));for(var s=0;s=r&&a>o){i=!0;break}}if(1==i&&o=e&&i>r&&(s+=r-n)}return s},e.correctTimeForHidden=function(t,i,o){return o=s(o).toDate().valueOf(),o-=e.getHiddenDurationBefore(t,i,o)},e.getHiddenDurationBefore=function(t,e,i){var o=0;i=s(i).toDate().valueOf();for(var n=0;n=e.start&&a=a&&(o+=a-r)}return o},e.getAccumulatedHiddenDuration=function(t,e,i){for(var s=0,o=0,n=e.start,r=0;r=e.start&&h=i)break;s+=h-a}}return s},e.snapAwayFromHidden=function(t,i,s,o){var n=e.isHidden(i,t);return 1==n.hidden?0>s?1==o?n.startDate-(n.endDate-i)-1:n.startDate-1:1==o?n.endDate+(i-n.startDate)+1:n.endDate+1:i},e.isHidden=function(t,e){for(var i=0;i=s&&o>t)return{hidden:!0,startDate:s,endDate:o}}return{hidden:!1,startDate:s,endDate:o}}},function(t,e,i){function s(){}var o=i(11),n=i(19),r=i(1),a=(i(7),i(9),i(21),i(26),i(36)),h=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.root.className="vis timeline root",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("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));var e=this;this.on("change",function(t){t&&1==t.queue?e._redrawTimer||(e._redrawTimer=setTimeout(function(){e._redrawTimer=null,e._redraw()},0)):e._redraw()}),this.hammer=n(this.dom.root,{preventDefault:!0}),this.listeners={};var 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.isActive()&&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={},this.redrawCount=0,!t)throw new Error("No container provided");t.appendChild(this.dom.root)},s.prototype.setOptions=function(t){if(t){var e=["width","height","minHeight","maxHeight","autoResize","start","end","orientation","clickToUse","dataAttributes","hiddenDates"];r.selectiveExtend(e,this.options,t),"hiddenDates"in this.options&&h.convertHiddenOptions(this.body,this.options.hiddenDates),"clickToUse"in t&&(t.clickToUse?this.activator||(this.activator=new a(this.dom.root)):this.activator&&(this.activator.destroy(),delete this.activator)),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.isActive=function(){return!this.activator||this.activator.active},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,this.activator&&(this.activator.destroy(),delete this.activator);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.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.getVisibleItems=function(){return this.itemSet&&this.itemSet.getVisibleItems()||[]},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(t){var e=this._getDataRange();if(null!==e.start||null!==e.end){var i=t&&void 0!==t.animate?t.animate:!0;this.range.setRange(e.start,e.end,i)}},s.prototype._getDataRange=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)}return{start:e,end:i}},s.prototype.setWindow=function(t,e,i){var s;if(1==arguments.length){var o=arguments[0];s=void 0!==o.animate?o.animate:!0,this.range.setRange(o.start,o.end,s)}else s=i&&void 0!==i.animate?i.animate:!0,this.range.setRange(t,e,s)},s.prototype.moveTo=function(t,e){var i=this.range.end-this.range.start,s=r.convert(t,"Date").valueOf(),o=s-i/2,n=s+i/2,a=e&&void 0!==e.animate?e.animate:!0;this.range.setRange(o,n,a)},s.prototype.getWindow=function(){var t=this.range.getRange();return{start:new Date(t.start),end:new Date(t.end)}},s.prototype.redraw=function(){this._redraw()},s.prototype._redraw=function(){var t=!1,e=this.options,i=this.props,s=this.dom;if(s){h.updateHiddenDates(this.body,this.options.hiddenDates),"top"==e.orientation?(r.addClassName(s.root,"top"),r.removeClassName(s.root,"bottom")):(r.removeClassName(s.root,"top"),r.addClassName(s.root,"bottom")),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;0===s.centerContainer.clientHeight&&(i.border.left=i.border.top,i.border.right=i.border.left),0===s.root.clientHeight&&(n=o),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),d=i.top.height+a+i.bottom.height+o+i.border.top+i.border.bottom;s.root.style.height=r.option.asSize(e.height,d+"px"),i.root.height=s.root.offsetHeight,i.background.height=i.root.height-o;var l=i.root.height-i.top.height-i.bottom.height-o;i.centerContainer.height=l,i.leftContainer.height=l,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 c=i.root.width-i.left.width-i.right.width-n;i.center.width=c,i.centerContainer.width=c,i.top.width=c,i.bottom.width=c,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+i.border.left+"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 p=this.props.scrollTop;"bottom"==e.orientation&&(p+=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=p+"px",s.left.style.left="0",s.left.style.top=p+"px",s.right.style.left="0",s.right.style.top=p+"px";var u=0==this.props.scrollTop?"hidden":"",m=this.props.scrollTop==this.props.scrollTopMin?"hidden":"";if(s.shadowTop.style.visibility=u,s.shadowBottom.style.visibility=m,s.shadowTopLeft.style.visibility=u,s.shadowBottomLeft.style.visibility=m,s.shadowTopRight.style.visibility=u,s.shadowBottomRight.style.visibility=m,this.components.forEach(function(e){t=e.redraw()||t}),t){var f=3;this.redrawCount0&&(this.props.scrollTop=0),this.props.scrollTope;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;this.props.top=this.body.domProps.top.height+this.body.domProps.border.top,this.props.left=this.body.domProps.left.width+this.body.domProps.border.left,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},f=0,g=t.axis+t.item.vertical;return this.groups[v].redraw(e,m,c),n.forEach(this.groups,function(t){var i=t==p?u:m,s=t.redraw(e,i,c);r=s||r,f+=t.height}),f=Math.max(f,g),this.stackDirty=!1,a.style.height=i(f),this.props.width=a.offsetWidth,this.props.height=f,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="0",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[g];return i||null},s.prototype._updateUngrouped=function(){{var t,e,i=this.groups[g];this.groups[v]}if(this.groupsData){if(i){i.hide(),delete this.groups[g];for(e in this.items)if(this.items.hasOwnProperty(e)){t=this.items[e],t.parent&&t.parent.remove(t);var s=this._getGroupId(t.data),o=this.groups[s];o&&o.add(t)||t.hide()}}}else if(!i){var n=null,r=null;i=new l(n,r,this),this.groups[g]=i;for(e in this.items)this.items.hasOwnProperty(e)&&(t=this.items[e],i.add(t));i.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",{queue:!0})},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._getType=function(t){return t.type||this.options.type||(t.end?"range":"box")},s.prototype._getGroupId=function(t){var e=this._getType(t);return"background"==e&&void 0==t.group?v:this.groupsData?t.group:g},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=e._getType(i),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",{queue:!0})},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",{queue:!0}))},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==g||t==v)throw new Error("Illegal group id. "+t+" is a reserved id.");var o=Object.create(e.options);n.extend(o,{height:null}),s=new l(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",{queue:!0})},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",{queue:!0})},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._getGroupId(t.data),i=this.groups[e];i&&i.add(t)},s.prototype._updateItem=function(t,e){var i=t.data.group;if(t.setData(e),i!=t.data.group){var s=this.groups[i];s&&s.remove(t);var o=this._getGroupId(t.data),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),t.parent&&t.parent.remove(t)},s.prototype._constructByEndArray=function(t){for(var e=[],i=0;i0||o.length>0)&&this.body.emitter.emit("select",{items:a})}},s.prototype._onAddItem=function(t){if(this.options.selectable&&this.options.editable.add){var e=this,i=this.options.snap||null,o=s.itemFromTarget(t);if(o){var r=e.itemsData.get(o.id);this.options.onUpdate(r,function(t){t&&e.itemsData.getDataSet().update(t)})}else{var a=n.getAbsoluteLeft(this.dom.frame),h=t.gesture.center.pageX-a,d=this.body.util.toTime(h),l=this.body.util.getScale(),c=this.body.util.getStep(),p={start:i?i(d,l,c):d,content:"new item"};if("range"===this.options.type){var u=this.body.util.toTime(h+this.props.width/5);p.end=i?i(u,l,c):u}p[this.itemsData._fieldId]=n.randomUUID();var m=this.groupFromTarget(t);m&&(p.group=m.groupId),this.options.onAdd(p,function(t){t&&e.itemsData.getDataSet().add(t)})}}},s.prototype._onMultiSelectItem=function(t){if(this.options.selectable){var e,i=s.itemFromTarget(t);if(i){e=this.getSelection();var o=t.gesture.touches[0]&&t.gesture.touches[0].shiftKey||!1;if(o){e.push(i.id);var n=s._getItemRange(this.itemsData.get(e,this.itemOptions));e=[];for(var r in this.items)if(this.items.hasOwnProperty(r)){var a=this.items[r],h=a.data.start,d=void 0!==a.data.end?a.data.end:h;h>=n.min&&d<=n.max&&e.push(a.id)}}else{var l=e.indexOf(i.id);-1==l?e.push(i.id):e.splice(l,1)}this.setSelection(e),this.body.emitter.emit("select",{items:this.getSelection()})}}},s._getItemRange=function(t){var e=null,i=null;return t.forEach(function(t){(null==i||t.starte)&&(e=t.end):(null==e||t.start>e)&&(e=t.start)}),{min:i,max:e}},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.prototype.groupFromTarget=function(t){for(var e=t.gesture.center.clientY,i=0;ia&&ea)return o}else if(0===i&&e0?t.step:1,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,s=864e5,o=36e5,n=6e4,r=1e3,a=1;1e3*e>t&&(this.scale="year",this.step=1e3),500*e>t&&(this.scale="year",this.step=500),100*e>t&&(this.scale="year",this.step=100),50*e>t&&(this.scale="year",this.step=50),10*e>t&&(this.scale="year",this.step=10),5*e>t&&(this.scale="year",this.step=5),e>t&&(this.scale="year",this.step=1),3*i>t&&(this.scale="month",this.step=3),i>t&&(this.scale="month",this.step=1),5*s>t&&(this.scale="day",this.step=5),2*s>t&&(this.scale="day",this.step=2),s>t&&(this.scale="day",this.step=1),s/2>t&&(this.scale="weekday",this.step=1),4*o>t&&(this.scale="hour",this.step=4),o>t&&(this.scale="hour",this.step=1),15*n>t&&(this.scale="minute",this.step=15),10*n>t&&(this.scale="minute",this.step=10),5*n>t&&(this.scale="minute",this.step=5),n>t&&(this.scale="minute",this.step=1),15*r>t&&(this.scale="second",this.step=15),10*r>t&&(this.scale="second",this.step=10),5*r>t&&(this.scale="second",this.step=5),r>t&&(this.scale="second",this.step=1),200*a>t&&(this.scale="millisecond",this.step=200),100*a>t&&(this.scale="millisecond",this.step=100),50*a>t&&(this.scale="millisecond",this.step=50),10*a>t&&(this.scale="millisecond",this.step=10),5*a>t&&(this.scale="millisecond",this.step=5),a>t&&(this.scale="millisecond",this.step=1)}},s.snap=function(t,e,i){var s=new Date(t.valueOf());if("year"==e){var o=s.getFullYear()+Math.round(s.getMonth()/12);s.setFullYear(Math.round(o/i)*i),s.setMonth(0),s.setDate(0),s.setHours(0),s.setMinutes(0),s.setSeconds(0),s.setMilliseconds(0)}else if("month"==e)s.getDate()>15?(s.setDate(1),s.setMonth(s.getMonth()+1)):s.setDate(1),s.setHours(0),s.setMinutes(0),s.setSeconds(0),s.setMilliseconds(0);else if("day"==e){switch(i){case 5:case 2:s.setHours(24*Math.round(s.getHours()/24));break;default:s.setHours(12*Math.round(s.getHours()/12))}s.setMinutes(0),s.setSeconds(0),s.setMilliseconds(0)}else if("weekday"==e){switch(i){case 5:case 2:s.setHours(12*Math.round(s.getHours()/12));break;default:s.setHours(6*Math.round(s.getHours()/6))}s.setMinutes(0),s.setSeconds(0),s.setMilliseconds(0)}else if("hour"==e){switch(i){case 4:s.setMinutes(60*Math.round(s.getMinutes()/60));break;default:s.setMinutes(30*Math.round(s.getMinutes()/30))}s.setSeconds(0),s.setMilliseconds(0)}else if("minute"==e){switch(i){case 15:case 10:s.setMinutes(5*Math.round(s.getMinutes()/5)),s.setSeconds(0);break;case 5:s.setSeconds(60*Math.round(s.getSeconds()/60));break;default:s.setSeconds(30*Math.round(s.getSeconds()/30))}s.setMilliseconds(0)}else if("second"==e)switch(i){case 15:case 10:s.setSeconds(5*Math.round(s.getSeconds()/5)),s.setMilliseconds(0);break;case 5:s.setMilliseconds(1e3*Math.round(s.getMilliseconds()/1e3));break;default:s.setMilliseconds(500*Math.round(s.getMilliseconds()/500))}else if("millisecond"==e){var n=i>5?i/2:1;s.setMilliseconds(Math.round(s.getMilliseconds()/n)*n)}return s},s.prototype.isMajor=function(){if(1==this.switchedYear)switch(this.switchedYear=!1,this.scale){case"year":case"month":case"weekday":case"day":case"hour":case"minute":case"second":case"millisecond":return!0;default:return!1}else if(1==this.switchedMonth)switch(this.switchedMonth=!1,this.scale){case"weekday":case"day":case"hour":case"minute":case"second":case"millisecond":return!0;default:return!1}else if(1==this.switchedDay)switch(this.switchedDay=!1,this.scale){case"millisecond":case"second":case"minute":case"hour":return!0;default:return!1}switch(this.scale){case"millisecond":return 0==this.current.getMilliseconds();case"second":return 0==this.current.getSeconds();case"minute":return 0==this.current.getHours()&&0==this.current.getMinutes();case"hour":return 0==this.current.getHours();case"weekday":case"day":return 1==this.current.getDate();case"month":return 0==this.current.getMonth();case"year":return!1;default:return!1}},s.prototype.getLabelMinor=function(t){void 0==t&&(t=this.current);var e=this.format.minorLabels[this.scale];return e&&e.length>0?o(t).format(e):""},s.prototype.getLabelMajor=function(t){void 0==t&&(t=this.current);var e=this.format.majorLabels[this.scale];return e&&e.length>0?o(t).format(e):""},s.prototype.getClassName=function(){function t(t){return t/h%2==0?" even":" odd"}function e(t){return t.isSame(new Date,"day")?" today":t.isSame(o().add(1,"day"),"day")?" tomorrow":t.isSame(o().add(-1,"day"),"day")?" yesterday":""}function i(t){return t.isSame(new Date,"week")?" current-week":""}function s(t){return t.isSame(new Date,"month")?" current-month":""}function n(t){return t.isSame(new Date,"year")?" current-year":""}var r=o(this.current),a=r.locale?r.locale("en"):r.lang("en"),h=this.step;switch(this.scale){case"millisecond":return t(a.milliseconds()).trim();case"second":return t(a.seconds()).trim();case"minute":return t(a.minutes()).trim();case"hour":var d=a.hours();return 4==this.step&&(d=d+"-"+(d+4)),d+"h"+e(a)+t(a.hours());case"weekday":return a.format("dddd").toLowerCase()+e(a)+i(a)+t(a.date());case"day":var l=a.date(),c=a.format("MMMM").toLowerCase();return"day"+l+" "+c+s(a)+t(l-1);case"month":return a.format("MMMM").toLowerCase()+s(a)+t(a.month());case"year":var p=a.year();return"year"+p+n(a)+t(p);default:return""}},t.exports=s},function(t,e,i){function s(t,e,i){this.groupId=t,this.subgroups={},this.subgroupIndex=0,this.subgroupOrderer=e&&e.subgroupOrder,this.itemSet=i,this.dom={},this.props={label:{width:0,height:0}},this.className=null,this.items={},this.visibleItems=[],this.orderedItems={byStart:[],byEnd:[]},this.checkRangedItems=!1;var s=this;this.itemSet.body.emitter.on("checkRangedItems",function(){s.checkRangedItems=!0}),this._create(),this.setData(e)}{var o=i(1),n=i(29);i(30)}s.prototype._create=function(){var t=document.createElement("div");t.className="vlabel",this.dom.label=t;var e=document.createElement("div");e.className="inner",t.appendChild(e),this.dom.inner=e;var i=document.createElement("div");i.className="group",i["timeline-group"]=this,this.dom.foreground=i,this.dom.background=document.createElement("div"),this.dom.background.className="group",this.dom.axis=document.createElement("div"),this.dom.axis.className="group",this.dom.marker=document.createElement("div"),this.dom.marker.style.visibility="hidden",this.dom.marker.innerHTML="?",this.dom.background.appendChild(this.dom.marker)},s.prototype.setData=function(t){var e=t&&t.content;e instanceof Element?this.dom.inner.appendChild(e):this.dom.inner.innerHTML=void 0!==e&&null!==e?e:this.groupId||"",this.dom.label.title=t&&t.title||"",this.dom.inner.firstChild?o.removeClassName(this.dom.inner,"hidden"):o.addClassName(this.dom.inner,"hidden");var i=t&&t.className||null;i!=this.className&&(this.className&&(o.removeClassName(this.dom.label,this.className),o.removeClassName(this.dom.foreground,this.className),o.removeClassName(this.dom.background,this.className),o.removeClassName(this.dom.axis,this.className)),o.addClassName(this.dom.label,i),o.addClassName(this.dom.foreground,i),o.addClassName(this.dom.background,i),o.addClassName(this.dom.axis,i),this.className=i),this.style&&(o.removeCssText(this.dom.label,this.style),this.style=null),t&&t.style&&(o.addCssText(this.dom.label,t.style),this.style=t.style)},s.prototype.getLabelWidth=function(){return this.props.label.width},s.prototype.redraw=function(t,e,i){var s=!1;this.visibleItems=this._updateVisibleItems(this.orderedItems,this.visibleItems,t);var r=this.dom.marker.clientHeight;r!=this.lastMarkerHeight&&(this.lastMarkerHeight=r,o.forEach(this.items,function(t){t.dirty=!0,t.displayed&&t.redraw()}),i=!0),this.itemSet.options.stack?n.stack(this.visibleItems,e,i):n.nostack(this.visibleItems,e,this.subgroups);var a=this._calculateHeight(e),h=this.dom.foreground;this.top=h.offsetTop,this.left=h.offsetLeft,this.width=h.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 d=0,l=this.visibleItems.length;l>d;d++){var c=this.visibleItems[d];c.repositionY(e)}return s},s.prototype._calculateHeight=function(t){var e,i=this.visibleItems;this.resetSubgroups();var s=this;if(i.length){var n=i[0].top,r=i[0].top+i[0].height;if(o.forEach(i,function(t){n=Math.min(n,t.top),r=Math.max(r,t.top+t.height),void 0!==t.data.subgroup&&(s.subgroups[t.data.subgroup].height=Math.max(s.subgroups[t.data.subgroup].height,t.height),s.subgroups[t.data.subgroup].visible=!0)}),n>t.axis){var a=n-t.axis;r-=a,o.forEach(i,function(t){t.top-=a})}e=r+t.item.vertical/2}else e=t.axis+t.item.vertical;return e=Math.max(e,this.props.label.height)},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),void 0!==t.data.subgroup&&(void 0===this.subgroups[t.data.subgroup]&&(this.subgroups[t.data.subgroup]={height:0,visible:!1,index:this.subgroupIndex,items:[]},this.subgroupIndex++),this.subgroups[t.data.subgroup].items.push(t)),this.orderSubgroups(),-1==this.visibleItems.indexOf(t)){var e=this.itemSet.body.range;this._checkIfVisible(t,this.visibleItems,e)}},s.prototype.orderSubgroups=function(){if(void 0!==this.subgroupOrderer){var t=[];if("string"==typeof this.subgroupOrderer){for(var e in this.subgroups)t.push({subgroup:e,sortField:this.subgroups[e].items[0].data[this.subgroupOrderer]});t.sort(function(t,e){return t.sortField-e.sortField})}else if("function"==typeof this.subgroupOrderer){for(var e in this.subgroups)t.push(this.subgroups[e].items[0].data);t.sort(this.subgroupOrderer)}if(t.length>0)for(var i=0;it?-1:l>=t?0:1};if(e.length>0)for(n=0;nl}),1==this.checkRangedItems)for(this.checkRangedItems=!1,n=0;nl})}for(n=0;n=0&&(n=e[r],!o(n));r--)void 0===s[n.id]&&(s[n.id]=!0,i.push(n));for(r=t+1;ro;o++)t[o].top=null;for(o=0,n=t.length;n>o;o++){var r=t[o];if(r.stack&&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&&l.stack&&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,i){var s,o,n;for(s=0,o=t.length;o>s;s++)if(void 0!==t[s].data.subgroup){n=e.axis;for(var r in i)i.hasOwnProperty(r)&&1==i[r].visible&&i[r].indexe.left&&t.top-s.vertical+ie.top}},function(t,e,i){function s(t,e,i){if(this.props={content:{width:0}},this.overflow=!1,t){if(void 0==t.start)throw new Error('Property "start" missing in item '+t.id);if(void 0==t.end)throw new Error('Property "end" missing in item '+t.id)}n.call(this,t,e,i)}var o=i(19),n=i(31);s.prototype=new n(null,null,null),s.prototype.baseClassName="item range",s.prototype.isVisible=function(t){return 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.dirty=!0),!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 item: parent has no foreground container element");e.appendChild(t.box)}if(this.displayed=!0,this.dirty){this._updateContents(this.dom.content),this._updateTitle(this.dom.box),this._updateDataAttributes(this.dom.box),this._updateStyle(this.dom.box);var i=(this.data.className?" "+this.data.className:"")+(this.selected?" selected":"");t.box.className=this.baseClassName+i,this.overflow="hidden"!==window.getComputedStyle(t.content).overflow,this.dom.content.style.maxWidth="none",this.props.content.width=this.dom.content.offsetWidth,this.height=this.dom.box.offsetHeight,this.dom.content.style.maxWidth="",this.dirty=!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,i=this.parent.width,s=this.conversion.toScreen(this.data.start),o=this.conversion.toScreen(this.data.end);-i>s&&(s=-i),o>2*i&&(o=2*i);var n=Math.max(o-s,1);switch(this.overflow?(this.left=s,this.width=n+this.props.content.width,e=this.props.content.width):(this.left=s,this.width=n,e=Math.min(o-s-2*this.options.padding,this.props.content.width)),this.dom.box.style.left=this.left+"px",this.dom.box.style.width=n+"px",this.options.align){case"left":this.dom.content.style.left="0";break;case"right":this.dom.content.style.left=Math.max(n-e-2*this.options.padding,0)+"px";break;case"center":this.dom.content.style.left=Math.max((n-e-2*this.options.padding)/2,0)+"px";break;default:t=this.overflow?o>0?Math.max(-s,0):-e:0>s?Math.min(-s,o-s-e-2*this.options.padding):0,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){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(19),n=i(1);s.prototype.stack=!0,s.prototype.select=function(){this.selected=!0,this.dirty=!0,this.displayed&&this.redraw()},s.prototype.unselect=function(){this.selected=!1,this.dirty=!0,this.displayed&&this.redraw()},s.prototype.setData=function(t){this.data=t,this.dirty=!0,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)},s.prototype._updateContents=function(t){var e;if(this.options.template){var i=this.parent.itemSet.itemsData.get(this.id);e=this.options.template(i)}else e=this.data.content;if(e!==this.content){if(e instanceof Element)t.innerHTML="",t.appendChild(e);else if(void 0!=e)t.innerHTML=e;else if("background"!=this.data.type||void 0!==this.data.content)throw new Error('Property "content" missing in item '+this.id);this.content=e}},s.prototype._updateTitle=function(t){null!=this.data.title?t.title=this.data.title||"":t.removeAttribute("title")},s.prototype._updateDataAttributes=function(t){if(this.options.dataAttributes&&this.options.dataAttributes.length>0){var e=[];if(Array.isArray(this.options.dataAttributes))e=this.options.dataAttributes;else{if("all"!=this.options.dataAttributes)return;e=Object.keys(this.data)}for(var i=0;is;s++){var n=this.visibleItems[s];n.repositionY(e)}return i},s.prototype.show=function(){this.dom.background.parentNode||this.itemSet.dom.background.appendChild(this.dom.background)},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(31);i(1)}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),this.dirty=!0),!this.parent)throw new Error("Cannot redraw item: no parent attached");if(!t.box.parentNode){var e=this.parent.dom.background;if(!e)throw new Error("Cannot redraw item: parent has no background container element");e.appendChild(t.box)}if(this.displayed=!0,this.dirty){this._updateContents(this.dom.content),this._updateTitle(this.dom.content),this._updateDataAttributes(this.dom.content),this._updateStyle(this.dom.box);var i=(this.data.className?" "+this.data.className:"")+(this.selected?" selected":"");t.box.className=this.baseClassName+i,this.overflow="hidden"!==window.getComputedStyle(t.content).overflow,this.props.content.width=this.dom.content.offsetWidth,this.height=0,this.dirty=!1}},s.prototype.show=r.prototype.show,s.prototype.hide=r.prototype.hide,s.prototype.repositionX=r.prototype.repositionX,s.prototype.repositionY=function(t){var e="top"===this.options.orientation;this.dom.content.style.top=e?"":"0",this.dom.content.style.bottom=e?"0":"";var i;if(void 0!==this.data.subgroup){var s=this.data.subgroup,o=this.parent.subgroups,r=o[s].index;if(1==e){i=this.parent.subgroups[s].height+t.item.vertical,i+=0==r?t.axis-.5*t.item.vertical:0;var a=this.parent.top;for(var h in o)o.hasOwnProperty(h)&&1==o[h].visible&&o[h].indexr&&(a+=o[h].height+t.item.vertical);i=this.parent.subgroups[s].height+t.item.vertical,this.dom.box.style.top=a+"px",this.dom.box.style.bottom=""}}else this.parent instanceof n?(i=Math.max(this.parent.height,this.parent.itemSet.body.domProps.center.height,this.parent.itemSet.body.domProps.centerContainer.height),this.dom.box.style.top=e?"0":"",this.dom.box.style.bottom=e?"":"0"):(i=this.parent.height,this.dom.box.style.top=this.parent.top+"px",this.dom.box.style.bottom="");this.dom.box.style.height=i+"px"},t.exports=s},function(t,e,i){function s(t){this.active=!1,this.dom={container:t},this.dom.overlay=document.createElement("div"),this.dom.overlay.className="overlay",this.dom.container.appendChild(this.dom.overlay),this.hammer=a(this.dom.overlay,{prevent_default:!1}),this.hammer.on("tap",this._onTapOverlay.bind(this));var e=this,i=["touch","pinch","doubletap","hold","dragstart","drag","dragend","mousewheel","DOMMouseScroll"];i.forEach(function(t){e.hammer.on(t,function(t){t.stopPropagation()})}),this.windowHammer=a(window,{prevent_default:!1}),this.windowHammer.on("tap",function(i){o(i.target,t)||e.deactivate()}),void 0!==this.keycharm&&this.keycharm.destroy(),this.keycharm=n(),this.escListener=this.deactivate.bind(this)}function o(t,e){for(;t;){if(t===e)return!0;t=t.parentNode}return!1}var n=i(37),r=i(11),a=i(19),h=i(1);r(s.prototype),s.current=null,s.prototype.destroy=function(){this.deactivate(),this.dom.overlay.parentNode.removeChild(this.dom.overlay),this.hammer=null,this.windowHammer=null},s.prototype.activate=function(){s.current&&s.current.deactivate(),s.current=this,this.active=!0,this.dom.overlay.style.display="none",h.addClassName(this.dom.container,"vis-active"),this.emit("change"),this.emit("activate"),this.keycharm.bind("esc",this.escListener)},s.prototype.deactivate=function(){this.active=!1,this.dom.overlay.style.display="",h.removeClassName(this.dom.container,"vis-active"),this.keycharm.unbind("esc",this.escListener),this.emit("change"),this.emit("deactivate")},s.prototype._onTapOverlay=function(t){this.activate(),t.stopPropagation()},t.exports=s},function(t,e){var i,s,o;!function(n,r){s=[],i=r,o="function"==typeof i?i.apply(e,s):i,!(void 0!==o&&(t.exports=o))}(this,function(){function t(t){var e,i=t&&t.preventDefault||!1,s=t&&t.container||window,o={},n={keydown:{},keyup:{}},r={};for(e=97;122>=e;e++)r[String.fromCharCode(e)]={code:65+(e-97),shift:!1};for(e=65;90>=e;e++)r[String.fromCharCode(e)]={code:e,shift:!0};for(e=0;9>=e;e++)r[""+e]={code:48+e,shift:!1};for(e=1;12>=e;e++)r["F"+e]={code:111+e,shift:!1};for(e=0;9>=e;e++)r["num"+e]={code:96+e,shift:!1};r["num*"]={code:106,shift:!1},r["num+"]={code:107,shift:!1},r["num-"]={code:109,shift:!1},r["num/"]={code:111,shift:!1},r["num."]={code:110,shift:!1},r.left={code:37,shift:!1},r.up={code:38,shift:!1},r.right={code:39,shift:!1},r.down={code:40,shift:!1},r.space={code:32,shift:!1},r.enter={code:13,shift:!1},r.shift={code:16,shift:void 0},r.esc={code:27,shift:!1},r.backspace={code:8,shift:!1},r.tab={code:9,shift:!1},r.ctrl={code:17,shift:!1},r.alt={code:18,shift:!1},r["delete"]={code:46,shift:!1},r.pageup={code:33,shift:!1},r.pagedown={code:34,shift:!1},r["="]={code:187,shift:!1},r["-"]={code:189,shift:!1},r["]"]={code:221,shift:!1},r["["]={code:219,shift:!1};var a=function(t){d(t,"keydown")},h=function(t){d(t,"keyup")},d=function(t,e){if(void 0!==n[e][t.keyCode]){for(var s=n[e][t.keyCode],o=0;oy;)y++,l=h.getCurrent(),c=h.isMajor(),u=h.getClassName(),f=m,m=this.body.util.toScreen(l),g=m-f,p&&(p.style.width=g+"px"),this.options.showMinorLabels&&this._repaintMinorText(m,h.getLabelMinor(),t,u),c&&this.options.showMajorLabels?(m>0&&(void 0==v&&(v=m),this._repaintMajorText(m,h.getLabelMajor(),t,u)),p=this._repaintMajorLine(m,t,u)):p=this._repaintMinorLine(m,t,u),h.next();if(this.options.showMajorLabels){var b=this.body.util.toTime(0),_=h.getLabelMajor(b),x=_.length*(this.props.majorCharWidth||10)+10;(void 0==v||v>x)&&this._repaintMajorText(0,_,t,u)}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,s){var o=this.dom.redundant.minorTexts.shift();if(!o){var n=document.createTextNode("");o=document.createElement("div"),o.appendChild(n),this.dom.foreground.appendChild(o)}this.dom.minorTexts.push(o),o.childNodes[0].nodeValue=e,o.style.top="top"==i?this.props.majorLabelHeight+"px":"0",o.style.left=t+"px",o.className="text minor "+s},s.prototype._repaintMajorText=function(t,e,i,s){var o=this.dom.redundant.majorTexts.shift();if(!o){var n=document.createTextNode(e);o=document.createElement("div"),o.appendChild(n),this.dom.foreground.appendChild(o)}this.dom.majorTexts.push(o),o.childNodes[0].nodeValue=e,o.className="text major "+s,o.style.top="top"==i?"0":this.props.minorLabelHeight+"px",o.style.left=t+"px"},s.prototype._repaintMinorLine=function(t,e,i){var s=this.dom.redundant.lines.shift();s||(s=document.createElement("div"),this.dom.background.appendChild(s)),this.dom.lines.push(s);var o=this.props;return s.style.top="top"==e?o.majorLabelHeight+"px":this.body.domProps.top.height+"px",s.style.height=o.minorLineHeight+"px",s.style.left=t-o.minorLineWidth/2+"px",s.className="grid vertical minor "+i,s},s.prototype._repaintMajorLine=function(t,e,i){var s=this.dom.redundant.lines.shift();s||(s=document.createElement("div"),this.dom.background.appendChild(s)),this.dom.lines.push(s);var o=this.props;return s.style.top="top"==e?"0":this.body.domProps.top.height+"px",s.style.left=t-o.majorLineWidth/2+"px",s.style.height=o.majorLineHeight+"px",s.className="grid vertical major "+i,s},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 major 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},t.exports=s},function(t,e,i){function s(t,e){this.body=t,this.defaultOptions={showCurrentTime:!0,locales:a,locale:"en"},this.options=o.extend({},this.defaultOptions),this.offset=0,this._create(),this.setOptions(e)}var o=i(1),n=i(23),r=i(2),a=i(40);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","locale","locales"],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((new Date).valueOf()+this.offset),i=this.body.util.toScreen(e),s=this.options.locales[this.options.locale],o=s.current+" "+s.time+": "+r(e).format("dddd, MMMM Do YYYY, H:mm:ss");o=o.charAt(0).toUpperCase()+o.substring(1),this.bar.style.left=i+"px",this.bar.title=o}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)},s.prototype.setCurrentTime=function(t){var e=o.convert(t,"Date").valueOf(),i=(new Date).valueOf();this.offset=e-i,this.redraw()},s.prototype.getCurrentTime=function(){return new Date((new Date).valueOf()+this.offset)},t.exports=s},function(t,e){e.en={current:"current",time:"time"},e.en_EN=e.en,e.en_US=e.en,e.nl={custom:"aangepaste",time:"tijd"},e.nl_NL=e.nl,e.nl_BE=e.nl},function(t,e,i){function s(t,e){this.body=t,this.defaultOptions={showCustomTime:!1,locales:h,locale:"en"},this.options=n.extend({},this.defaultOptions),this.customTime=new Date,this.eventParams={},this._create(),this.setOptions(e)}var o=i(19),n=i(1),r=i(23),a=i(2),h=i(40);s.prototype=new r,s.prototype.setOptions=function(t){t&&n.selectiveExtend(["showCustomTime","locale","locales"],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),i=this.options.locales[this.options.locale],s=i.time+": "+a(this.customTime).format("dddd, MMMM Do YYYY, H:mm:ss");s=s.charAt(0).toUpperCase()+s.substring(1),this.bar.style.left=e+"px",this.bar.title=s}else this.bar.parentNode&&this.bar.parentNode.removeChild(this.bar);return!1},s.prototype.setCustomTime=function(t){this.customTime=n.convert(t,"Date"),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,s){if(!(Array.isArray(i)||i instanceof n)&&i instanceof Object){var r=s;s=i,i=r}var h=this;this.defaultOptions={start:null,end:null,autoResize:!0,orientation:"bottom",width:null,height:null,maxHeight:null,minHeight:null},this.options=o.deepExtend({},this.defaultOptions),this._create(t),this.components=[],this.body={dom:this.dom,domProps:this.props,emitter:{on:this.on.bind(this),off:this.off.bind(this),emit:this.emit.bind(this)},hiddenDates:[],util:{toScreen:h._toScreen.bind(h),toGlobalScreen:h._toGlobalScreen.bind(h),toTime:h._toTime.bind(h),toGlobalTime:h._toGlobalTime.bind(h)}},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.currentTime=new l(this.body),this.components.push(this.currentTime),this.customTime=new c(this.body),this.components.push(this.customTime),this.linegraph=new p(this.body),this.components.push(this.linegraph),this.itemsData=null,this.groupsData=null,s&&this.setOptions(s),i&&this.setGroups(i),e?this.setItems(e):this._redraw()}var o=(i(11),i(19),i(1)),n=i(7),r=i(9),a=i(21),h=i(25),d=i(38),l=i(39),c=i(41),p=i(43);s.prototype=new h,s.prototype.setItems=function(t){var e,i=null==this.itemsData;if(e=t?t instanceof n||t instanceof r?t:new n(t,{type:{start:"Date",end:"Date"}}):null,this.itemsData=e,this.linegraph&&this.linegraph.setItems(e),i)if(void 0!=this.options.start||void 0!=this.options.end){var s=void 0!=this.options.start?this.options.start:null,o=void 0!=this.options.end?this.options.end:null;this.setWindow(s,o,{animate:!1})}else this.fit({animate:!1})},s.prototype.setGroups=function(t){var e;e=t?t instanceof n||t instanceof r?t:new n(t):null,this.groupsData=e,this.linegraph.setGroups(e)},s.prototype.getLegend=function(t,e,i){return void 0===e&&(e=15),void 0===i&&(i=15),void 0!==this.linegraph.groups[t]?this.linegraph.groups[t].getLegend(e,i):"cannot find group:"+t},s.prototype.isGroupVisible=function(t){return void 0!==this.linegraph.groups[t]?this.linegraph.groups[t].visible&&(void 0===this.linegraph.options.groups.visibility[t]||1==this.linegraph.options.groups.visibility[t]):!1},s.prototype.getItemRange=function(){var t=null,e=null;for(var i in this.linegraph.groups)if(this.linegraph.groups.hasOwnProperty(i)&&1==this.linegraph.groups[i].visible)for(var s=0;sr?r:t,e=null==e?r:r>e?r:e}return{min:null!=t?new Date(t):null,max:null!=e?new Date(e):null}},t.exports=s},function(t,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,handleOverlap:"overlap",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,alignZeros:!0,customRange:{left:{min:void 0,max:void 0},right:{min:void 0,max:void 0}}},legend:{enabled:!1,icons:!0,left:{visible:!0,position:"top-left"},right:{visible:!0,position:"top-right"}},groups:{visibility:{}}},this.options=o.extend({},this.defaultOptions),this.dom={},this.props={},this.hammer=null,this.groups={},this.abortedGraphUpdate=!1,this.updateSVGheight=!1,this.updateSVGheightOnResize=!1;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.COUNTER=0,this.body.emitter.on("rangechanged",function(){i.lastStart=i.body.range.start,i.svg.style.left=o.option.asSize(-i.props.width),i.redraw.call(i,!0)}),this._create(),this.framework={svg:this.svg,svgElements:this.svgElements,options:this.options,groups:this.groups},this.body.emitter.emit("change")}var o=i(1),n=i(6),r=i(7),a=i(9),h=i(23),d=i(44),l=i(46),c=i(50),p=i(49),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.groups),this.options.dataAxis.orientation="right",this.yAxisRight=new d(this.body,this.options.dataAxis,this.svg,this.options.groups),delete this.options.dataAxis.orientation,this.legendLeft=new c(this.body,this.options.legend,"left",this.options.groups),this.legendRight=new c(this.body,this.options.legend,"right",this.options.groups),this.show()},s.prototype.setOptions=function(t){if(t){var e=["sampling","defaultGroup","height","graphHeight","yAxisOrientation","style","barChart","dataAxis","sort","groups"];void 0===t.graphHeight&&void 0!==t.height&&void 0!==this.body.domProps.centerContainer.height?(this.updateSVGheight=!0,this.updateSVGheightOnResize=!0):void 0!==this.body.domProps.centerContainer.height&&void 0!==t.graphHeight&&parseInt((t.graphHeight+"").replace("px",""))0){var d=this.body.util.toGlobalTime(-this.body.domProps.root.width),l=this.body.util.toGlobalTime(2*this.body.domProps.root.width),c={};for(this._getRelevantData(a,c,d,l),this._applySampling(a,c),e=0;eu&&console.log("WARNING: there may be an infinite loop in the _updateGraph emitter cycle."),this.COUNTER=0,this.abortedGraphUpdate=!1,e=0;e0)for(r=0;rs){d.push(h);break}d.push(h)}}else for(a=0;ai&&h.x0)for(var s=0;s0){var n=1,r=o.length,a=this.body.util.toGlobalScreen(o[o.length-1].x)-this.body.util.toGlobalScreen(o[0].x),h=r/a;n=Math.min(Math.ceil(.2*r),Math.max(1,Math.round(h)));for(var d=[],l=0;r>l;l+=n)d.push(o[l]);e[t[s]]=d}}},s.prototype._getYRanges=function(t,e,i){var s,o,n,r,a=[],h=[];if(t.length>0){for(n=0;n0&&(o=this.groups[t[n]],"stack"==r.barChart.handleOverlap&&"bar"==r.style?"left"==r.yAxisOrientation?a=a.concat(o.getYRange(s)):h=h.concat(o.getYRange(s)):i[t[n]]=o.getYRange(s,t[n]));p.getStackedBarYRange(a,i,t,"__barchartLeft","left"),p.getStackedBarYRange(h,i,t,"__barchartRight","right")}},s.prototype._updateYAxis=function(t,e){var i,s,o=!1,n=!1,r=!1,a=1e9,h=1e9,d=-1e9,l=-1e9;if(t.length>0){for(var c=0;ci?i:a,d=s>d?s:d):(r=!0,h=h>i?i:h,l=s>l?s:l));1==n&&this.yAxisLeft.setRange(a,d),1==r&&this.yAxisRight.setRange(h,l)}return o=this._toggleAxisVisiblity(n,this.yAxisLeft)||o,o=this._toggleAxisVisiblity(r,this.yAxisRight)||o,1==r&&1==n?(this.yAxisLeft.drawIcons=!0,this.yAxisRight.drawIcons=!0):(this.yAxisLeft.drawIcons=!1,this.yAxisRight.drawIcons=!1),this.yAxisRight.master=!n,0==this.yAxisRight.master?(this.yAxisLeft.lineOffset=1==r?this.yAxisRight.width:0,o=this.yAxisLeft.redraw()||o,this.yAxisRight.stepPixelsForced=this.yAxisLeft.stepPixels,this.yAxisRight.zeroCrossing=this.yAxisLeft.zeroCrossing,o=this.yAxisRight.redraw()||o):o=this.yAxisRight.redraw()||o,-1!=t.indexOf("__barchartLeft")&&t.splice(t.indexOf("__barchartLeft"),1),-1!=t.indexOf("__barchartRight")&&t.splice(t.indexOf("__barchartRight"),1),o},s.prototype._toggleAxisVisiblity=function(t,e){var i=!1;return 0==t?e.dom.frame.parentNode&&0==e.hidden&&(e.hide(),i=!0):e.dom.frame.parentNode||1!=e.hidden||(e.show(),i=!0),i},s.prototype._convertXcoordinates=function(t){for(var e,i,s=[],o=this.body.util.toScreen,n=0;n0&&(t=0),this.range.start=t,this.range.end=e},s.prototype.redraw=function(){var t=!1,e=0;this.dom.lineContainer.style.top=this.body.domProps.scrollTop+"px";for(var i in this.groups)this.groups.hasOwnProperty(i)&&(1!=this.groups[i].visible||void 0!==this.linegraphOptions.visibility[i]&&1!=this.linegraphOptions.visibility[i]||e++);if(0==this.amountOfGroups||0==e)this.hide();else{this.show(),this.height=Number(this.linegraphSVG.style.height.replace("px","")),this.dom.lineContainer.style.height=this.height+"px",this.width=1==this.options.visible?Number((""+this.options.width).replace("px","")):0;var s=this.props,o=this.dom.frame;o.className="dataaxis",this._calculateCharSize();var n=this.options.orientation,r=this.options.showMinorLabels,a=this.options.showMajorLabels;s.minorLabelHeight=r?s.minorCharHeight:0,s.majorLabelHeight=a?s.majorCharHeight:0,s.minorLineWidth=this.body.dom.backgroundHorizontal.offsetWidth-this.lineOffset-this.width+2*this.options.minorLinesOffset,s.minorLineHeight=1,s.majorLineWidth=this.body.dom.backgroundHorizontal.offsetWidth-this.lineOffset-this.width+2*this.options.majorLinesOffset,s.majorLineHeight=1,"left"==n?(o.style.top="0",o.style.left="0",o.style.bottom="",o.style.width=this.width+"px",o.style.height=this.height+"px",this.props.width=this.body.domProps.left.width,this.props.height=this.body.domProps.left.height):(o.style.top="",o.style.bottom="0",o.style.left="0",o.style.width=this.width+"px",o.style.height=this.height+"px",this.props.width=this.body.domProps.right.width,this.props.height=this.body.domProps.right.height),t=this._redrawLabels(),t=this._isResized()||t,1==this.options.icons?this._redrawGroupIcons():this._cleanupIcons(),this._redrawTitle(n)}return t},s.prototype._redrawLabels=function(){var t=!1;n.prepareElements(this.DOMelements.lines),n.prepareElements(this.DOMelements.labels);var e=this.options.orientation,i=this.master?this.props.majorCharHeight||10:this.stepPixelsForced,s=new a(this.range.start,this.range.end,i,this.dom.frame.offsetHeight,this.options.customRange[this.options.orientation],0==this.master&&this.options.alignZeros);this.step=s;var o=(this.dom.frame.offsetHeight-s.deadSpace*(this.dom.frame.offsetHeight/s.marginRange))/((s.marginRange-s.deadSpace)/s.step);this.stepPixels=o;var r=this.height/o,h=0;if(0==this.master){o=this.stepPixelsForced,h=Math.round(this.dom.frame.offsetHeight/o-r);for(var d=0;.5*h>d;d++)s.previous();if(r=this.height/o,-1!=this.zeroCrossing&&1==this.options.alignZeros){var l=s.marginEnd/s.step-this.zeroCrossing;if(l>0)for(var d=0;l>d;d++)s.next();else if(0>l)for(var d=0;-l>d;d++)s.previous()}}else r+=.25;this.valueAtZero=s.marginEnd;var c,p=0,u=1;void 0!==this.options.format[e]&&(c=this.options.format[e].decimals),this.maxLabelSize=0;for(var m=0;u=0&&this._redrawLabel(m-2,s.getCurrent(c),e,"yAxis major",this.props.majorCharHeight),this._redrawLine(m,e,"grid horizontal major",this.options.majorLinesOffset,this.props.majorLineWidth)):this._redrawLine(m,e,"grid horizontal minor",this.options.minorLinesOffset,this.props.minorLineWidth),1==this.master&&0==s.current&&(this.zeroCrossing=u),u++}this.conversionFactor=0==this.master?m/(this.valueAtZero-s.current):this.dom.frame.offsetHeight/s.marginRange;var g=0;void 0!==this.options.title[e]&&void 0!==this.options.title[e].text&&(g=this.props.titleCharHeight);var v=1==this.options.icons?Math.max(this.options.iconWidth,g)+this.options.labelOffsetX+15:g+this.options.labelOffsetX+15;return this.maxLabelSize>this.width-v&&1==this.options.visible?(this.width=this.maxLabelSize+v,this.options.width=this.width+"px",n.cleanupElements(this.DOMelements.lines),n.cleanupElements(this.DOMelements.labels),this.redraw(),t=!0):this.maxLabelSizethis.minWidth?(this.width=Math.max(this.minWidth,this.maxLabelSize+v),this.options.width=this.width+"px",n.cleanupElements(this.DOMelements.lines),n.cleanupElements(this.DOMelements.labels),this.redraw(),t=!0):(n.cleanupElements(this.DOMelements.lines),n.cleanupElements(this.DOMelements.labels),t=!1),t},s.prototype.convertValue=function(t){var e=this.valueAtZero-t,i=e*this.conversionFactor;return i},s.prototype._redrawLabel=function(t,e,i,s,o){var r=n.getDOMElement("div",this.DOMelements.labels,this.dom.frame);r.className=s,r.innerHTML=e,"left"==i?(r.style.left="-"+this.options.labelOffsetX+"px",r.style.textAlign="right"):(r.style.right="-"+this.options.labelOffsetX+"px",r.style.textAlign="left"),r.style.top=t-.5*o+this.options.labelOffsetY+"px",e+="";var a=Math.max(this.props.majorCharWidth,this.props.minorCharWidth);this.maxLabelSizen&&(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.setFirst=function(t){void 0===t&&(t={});var e=void 0===t.min?this._start-2*this.scale*this.minorSteps[this.stepIndex]:t.min,i=void 0===t.max?this._end+this.scale*this.minorSteps[this.stepIndex]:t.max;this.marginEnd=void 0===t.max?this.roundToMinor(i):t.max,this.marginStart=void 0===t.min?this.roundToMinor(e):t.min,1==this.alignZeros&&(this.marginEnd-this.marginStart)%this.step!=0&&(this.marginEnd+=this.marginEnd%this.step),this.deadSpace=this.roundToMinor(i)-i+this.roundToMinor(e)-e,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(t){var e=Math.abs(this.current)0;s--){if("0"!=i[s]){if("."==i[s]||","==i[s]){i=i.slice(0,s);break}break}i=i.slice(0,s)}}else{var o="",n=i.indexOf("e");if(-1!=n&&(o=i.slice(n),i=i.slice(0,n)),n=Math.max(i.indexOf(","),i.indexOf(".")),-1===n?(0!==t&&(i+="."),n=i.length+t):0!==t&&(n+=t+1),n>i.length)for(var r=n-i.length;r>0;r--)i+="0";else i=i.slice(0,n);i+=o}return i},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,i,s){this.id=e;var n=["sampling","style","sort","yAxisOrientation","barChart","drawPoints","shaded","catmullRom"];this.options=o.selectiveBridgeObject(n,i),this.usingDefaultStyle=void 0===t.className,this.groupsUsingDefaultStyles=s,this.zeroPosition=0,this.update(t),1==this.usingDefaultStyle&&(this.groupsUsingDefaultStyles[0]+=1),this.itemsData=[],this.visible=void 0===t.visible?!0:t.visible}var o=i(1),n=i(6),r=i(47),a=i(49),h=i(48);s.prototype.setItems=function(t){null!=t?(this.itemsData=t,1==this.options.sort&&this.itemsData.sort(function(t,e){return t.x-e.x})):this.itemsData=[]},s.prototype.setZeroPosition=function(t){this.zeroPosition=t},s.prototype.setOptions=function(t){if(void 0!==t){var e=["sampling","style","sort","yAxisOrientation","barChart"];o.selectiveDeepExtend(e,this.options,t),o.mergeOptions(this.options,t,"catmullRom"),o.mergeOptions(this.options,t,"drawPoints"),o.mergeOptions(this.options,t,"shaded"),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))}"line"==this.options.style?this.type=new r(this.id,this.options):"bar"==this.options.style?this.type=new a(this.id,this.options):"points"==this.options.style&&(this.type=new h(this.id,this.options))},s.prototype.update=function(t){this.group=t,this.content=t.content||"graph",this.className=t.className||this.className||"graphGroup"+this.groupsUsingDefaultStyles[0]%10,this.visible=void 0===t.visible?!0:t.visible,this.style=t.style,this.setOptions(t.options)},s.prototype.drawIcon=function(t,e,i,s,o,r){var a,h,d=.5*r,l=n.getSVGElement("rect",i,s);if(l.setAttributeNS(null,"x",t),l.setAttributeNS(null,"y",e-d),l.setAttributeNS(null,"width",o),l.setAttributeNS(null,"height",2*d),l.setAttributeNS(null,"class","outline"),"line"==this.options.style)a=n.getSVGElement("path",i,s),a.setAttributeNS(null,"class",this.className),void 0!==this.style&&a.setAttributeNS(null,"style",this.style),a.setAttributeNS(null,"d","M"+t+","+e+" L"+(t+o)+","+e),1==this.options.shaded.enabled&&(h=n.getSVGElement("path",i,s),"top"==this.options.shaded.orientation?h.setAttributeNS(null,"d","M"+t+", "+(e-d)+"L"+t+","+e+" L"+(t+o)+","+e+" L"+(t+o)+","+(e-d)):h.setAttributeNS(null,"d","M"+t+","+e+" L"+t+","+(e+d)+" L"+(t+o)+","+(e+d)+"L"+(t+o)+","+e),h.setAttributeNS(null,"class",this.className+" iconFill")),1==this.options.drawPoints.enabled&&n.drawPoint(t+.5*o,e,this,i,s);else{var c=Math.round(.3*o),p=Math.round(.4*r),u=Math.round(.75*r),m=Math.round((o-2*c)/3);n.drawBar(t+.5*c+m,e+d-p-1,c,p,this.className+" bar",i,s),n.drawBar(t+1.5*c+m+2,e+d-u-1,c,u,this.className+" bar",i,s)}},s.prototype.getLegend=function(t,e){var i=document.createElementNS("http://www.w3.org/2000/svg","svg");return this.drawIcon(0,.5*e,[],i,t,e),{icon:i,label:this.content,orientation:this.options.yAxisOrientation}},s.prototype.getYRange=function(t){return this.type.getYRange(t)},s.prototype.draw=function(t,e,i){this.type.draw(t,e,i)},t.exports=s},function(t,e,i){function s(t,e){this.groupId=t,this.options=e}var o=i(6),n=i(48);s.prototype.getYRange=function(t){for(var e=t[0].y,i=t[0].y,s=0;st[s].y?t[s].y:e,i=i0){var r,a,h=Number(i.svg.style.height.replace("px",""));if(r=o.getSVGElement("path",i.svgElements,i.svg),r.setAttributeNS(null,"class",e.className),void 0!==e.style&&r.setAttributeNS(null,"style",e.style),a=1==e.options.catmullRom.enabled?s._catmullRom(t,e):s._linear(t),1==e.options.shaded.enabled){var d,l=o.getSVGElement("path",i.svgElements,i.svg);d="top"==e.options.shaded.orientation?"M"+t[0].x+",0 "+a+"L"+t[t.length-1].x+",0":"M"+t[0].x+","+h+" "+a+"L"+t[t.length-1].x+","+h,l.setAttributeNS(null,"class",e.className+" fill"),void 0!==e.options.shaded.style&&l.setAttributeNS(null,"style",e.options.shaded.style),l.setAttributeNS(null,"d",d)}r.setAttributeNS(null,"d","M"+a),1==e.options.drawPoints.enabled&&n.draw(t,e,i)}},s._catmullRomUniform=function(t){for(var e,i,s,o,n,r,a=Math.round(t[0].x)+","+Math.round(t[0].y)+" ",h=1/6,d=t.length,l=0;d-1>l;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._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,f,g,v,y,b,_,x,w=Math.round(t[0].x)+","+Math.round(t[0].y)+" ",D=t.length,M=0;D-1>M;M++)s=0==M?t[0]:t[M-1],o=t[M],n=t[M+1],r=D>M+2?t[M+2]:n,d=Math.sqrt(Math.pow(s.x-o.x,2)+Math.pow(s.y-o.y,2)),l=Math.sqrt(Math.pow(o.x-n.x,2)+Math.pow(o.y-n.y,2)),c=Math.sqrt(Math.pow(n.x-r.x,2)+Math.pow(n.y-r.y,2)),g=Math.pow(c,i),y=Math.pow(c,2*i),v=Math.pow(l,i),b=Math.pow(l,2*i),x=Math.pow(d,i),_=Math.pow(d,2*i),p=2*_+3*x*v+b,u=2*y+3*g*v+b,m=3*x*(x+v),m>0&&(m=1/m),f=3*g*(g+v),f>0&&(f=1/f),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)*f,y:(y*o.y+u*n.y-b*r.y)*f},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._linear=function(t){for(var e="",i=0;it[s].y?t[s].y:e,i=it[s].y?t[s].y:e,i=i0&&(n=Math.min(n,Math.abs(c[d-1].x-r))),a=s._getSafeDrawData(n,h,m);else{var g=d+(p[r].amount-p[r].resolved),v=d-(p[r].resolved+1);g0&&(n=Math.min(n,Math.abs(c[v].x-r))),a=s._getSafeDrawData(n,h,m),p[r].resolved+=1,"stack"==h.options.barChart.handleOverlap?(f=p[r].accumulated,p[r].accumulated+=h.zeroPosition-c[d].y):"sideBySide"==h.options.barChart.handleOverlap&&(a.width=a.width/p[r].amount,a.offset+=p[r].resolved*a.width-.5*a.width*(p[r].amount+1),"left"==h.options.barChart.align?a.offset-=.5*a.width:"right"==h.options.barChart.align&&(a.offset+=.5*a.width))}o.drawBar(c[d].x+a.offset,c[d].y-f,a.width,h.zeroPosition-c[d].y,h.className+" bar",i.svgElements,i.svg),1==h.options.drawPoints.enabled&&o.drawPoint(c[d].x+a.offset,c[d].y,h,i.svgElements,i.svg)}},s._getDataIntersections=function(t,e){for(var i,s=0;s0&&(i=Math.min(i,Math.abs(e[s-1].x-e[s].x))),0==i&&(void 0===t[e[s].x]&&(t[e[s].x]={amount:0,resolved:0,accumulated:0}),t[e[s].x].amount+=1)},s._getSafeDrawData=function(t,e,i){var s,o;return t0?(s=i>t?i:t,o=0,"left"==e.options.barChart.align?o-=.5*t:"right"==e.options.barChart.align&&(o+=.5*t)):(s=e.options.barChart.width,o=0,"left"==e.options.barChart.align?o-=.5*e.options.barChart.width:"right"==e.options.barChart.align&&(o+=.5*e.options.barChart.width)),{width:s,offset:o}},s.getStackedBarYRange=function(t,e,i,o,n){if(t.length>0){t.sort(function(t,e){return t.x==e.x?t.groupId-e.groupId:t.x-e.x});var r={};s._getDataIntersections(r,t),e[o]=s._getStackedBarYRange(r,t),e[o].yAxisOrientation=n,i.push(o)}},s._getStackedBarYRange=function(t,e){for(var i,s=e[0].y,o=e[0].y,n=0;ne[n].y?e[n].y:s,o=ot[r].accumulated?t[r].accumulated:s,o=o"));this.dom.textArea.innerHTML=s,this.dom.textArea.style.lineHeight=.75*this.options.iconSize+this.options.iconSpacing+"px"}},s.prototype.drawLegendIcons=function(){if(this.dom.frame.parentNode){n.prepareElements(this.svgElements);var t=window.getComputedStyle(this.dom.frame).paddingTop,e=Number(t.replace("px","")),i=e,s=this.options.iconSize,o=.75*this.options.iconSize,r=e+.5*o+3;this.svg.style.width=s+5+e+"px";for(var a in this.groups)this.groups.hasOwnProperty(a)&&(1!=this.groups[a].visible||void 0!==this.linegraphOptions.visibility[a]&&1!=this.linegraphOptions.visibility[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,i){if(!(this instanceof s))throw new SyntaxError("Constructor must be called with the new operator");this._determineBrowserMethod(),this._initializeMixinLoaders(),this.containerElement=t,this.renderRefreshRate=60,this.renderTimestep=1e3/this.renderRefreshRate,this.renderTime=0,this.physicsTime=0,this.runDoubleSpeed=!1,this.physicsDiscreteStepsize=.5,this.initializing=!0,this.triggerFunctions={add:null,edit:null,editEdge:null,connect:null,del:null};var o=function(t,e,i,s){if(e==t)return.5;var o=1/(e-t);return Math.max(0,(s-t)*o)};this.defaultOptions={nodes:{customScalingFunction:o,mass:1,radiusMin:10,radiusMax:30,radius:10,shape:"ellipse",image:void 0,widthMin:16,widthMax:64,fontColor:"black",fontSize:14,fontFace:"verdana",fontFill:void 0,fontStrokeWidth:0,fontStrokeColor:"#ffffff",fontDrawThreshold:3,scaleFontWithValue:!1,fontSizeMin:14,fontSizeMax:30,fontSizeMaxVisible:30,level:-1,color:{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"},hover:{border:"#2B7CE9",background:"#D2E5FF"}},group:void 0,borderWidth:1,borderWidthSelected:void 0},edges:{customScalingFunction:o,widthMin:1,widthMax:15,width:1,widthSelectionMultiplier:2,hoverWidth:1.5,style:"line",color:{color:"#848484",highlight:"#848484",hover:"#848484"},opacity:1,fontColor:"#343434",fontSize:14,fontFace:"arial",fontFill:"white",fontStrokeWidth:0,fontStrokeColor:"white",labelAlignment:"horizontal",arrowScaleFactor:1,dash:{length:10,gap:5,altLength:void 0},inheritColor:"from",useGradients:!1},configurePhysics:!1,physics:{barnesHut:{enabled:!0,thetaInverted:2,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},navigation:{enabled:!1},keyboard:{enabled:!1,speed:{x:10,y:10,zoom:.02},bindToWindow:!0},dataManipulation:{enabled:!1,initiallyVisible:!1},hierarchicalLayout:{enabled:!1,levelSeparation:150,nodeSpacing:100,direction:"UD",layout:"hubsize"},freezeForStabilization:!1,smoothCurves:{enabled:!0,dynamic:!0,type:"continuous",roundness:.5},maxVelocity:50,minVelocity:.1,stabilize:!0,stabilizationIterations:1e3,zoomExtentOnStabilize:!0,locale:"en",locales:_,tooltip:{delay:300,fontColor:"black",fontSize:14,fontFace:"verdana",color:{border:"#666",background:"#FFFFC6"}},dragNetwork:!0,dragNodes:!0,zoomable:!0,hover:!1,hideEdgesOnDrag:!1,hideNodesOnDrag:!1,width:"100%",height:"100%",selectable:!0,useDefaultGroups:!0},this.constants=a.extend({},this.defaultOptions),this.pixelRatio=1,this.hoverObj={nodes:{},edges:{}},this.controlNodesActive=!1,this.navigationHammers={existing:[],_new:[]},this.animationSpeed=1/this.renderRefreshRate,this.animationEasingFunction="easeInOutQuint",this.animating=!1,this.easingTime=0,this.sourceScale=0,this.targetScale=0,this.sourceTranslation=0,this.targetTranslation=0,this.lockedOnNodeId=null,this.lockedOnNodeOffset=null,this.touchTime=0,this.redrawRequested=!1;var n=this;this.groups=new u,this.images=new m,this.images.setOnloadCallback(function(){n._requestRedraw()}),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.freezeSimulationEnabled=!1,this.cachedFunctions={},this.startedStabilization=!1,this.stabilized=!1,this.stabilizationIterations=null,this.draggingNodes=!1,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,e.data),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.constants.stabilize&&this.zoomExtent({duration:0},!0,this.constants.clustering.enabled),this.constants.clustering.enabled&&this.startWithClustering()}var o=i(11),n=i(19),r=i(37),a=i(1),h=i(22),d=i(7),l=i(9),c=i(57),p=i(58),u=i(54),m=i(55),f=i(53),g=i(52),v=i(56),y=i(59),b=i(36),_=i(70);i(71),o(s.prototype),s.prototype._determineBrowserMethod=function(){var t=navigator.userAgent.toLowerCase();this.requiresTimeout=!1,-1!=t.indexOf("msie 9.0")?this.requiresTimeout=!0:-1!=t.indexOf("safari")&&t.indexOf("chrome")<=-1&&(this.requiresTimeout=!0)},s.prototype._getScriptPath=function(){for(var t=document.getElementsByTagName("script"),e=0;e0)for(var r=0;re.boundingBox.left&&(o=e.boundingBox.left),ne.boundingBox.bottom&&(i=e.boundingBox.top),se.boundingBox.left&&(o=e.boundingBox.left),ne.boundingBox.bottom&&(i=e.boundingBox.top),s.5*this.nodeIndices.length)return void this.zoomExtent(t,!1,i);s=this._getRange(t.nodes);var h=this.nodeIndices.length;o=1==this.constants.smoothCurves?1==this.constants.clustering.enabled&&h>=this.constants.clustering.initialMaxNodes?49.07548/(h+142.05338)+91444e-8:12.662/(h+7.4147)+.0964822:1==this.constants.clustering.enabled&&h>=this.constants.clustering.initialMaxNodes?77.5271985/(h+187.266146)+476710517e-13:30.5062972/(h+19.93597763)+.08413486;var d=Math.min(this.frame.canvas.clientWidth/600,this.frame.canvas.clientHeight/600);o*=d}else{s=this._getRange(t.nodes);var l=1.1*Math.abs(s.maxX-s.minX),c=1.1*Math.abs(s.maxY-s.minY),p=this.frame.canvas.clientWidth/l,u=this.frame.canvas.clientHeight/c;o=u>=p?p:u}o>1&&(o=1);var m=this._findCenter(s);if(0==i){var t={position:m,scale:o,animation:t};this.moveTo(t),this.moving=!0,this.start()}else m.x*=o,m.y*=o,m.x-=.5*this.frame.canvas.clientWidth,m.y-=.5*this.frame.canvas.clientHeight,this._setScale(o),this._setTranslation(-m.x,-m.y)},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),this._unselectAll(!0),this.initializing=!0,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(1==this.constants.dataManipulation.enabled&&this._createManipulatorBar(),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);this._putDataInSector(),0==e&&(1==this.constants.hierarchicalLayout.enabled?(this._resetLevels(),this._setupHierarchicalLayout()):1==this.constants.stabilize&&this._stabilize(),this.start()),this.initializing=!1},s.prototype.setOptions=function(t){if(t){var e,i=["nodes","edges","smoothCurves","hierarchicalLayout","clustering","navigation","keyboard","dataManipulation","onAdd","onEdit","onEditEdge","onConnect","onDelete","clickToUse"];if(a.selectiveNotDeepExtend(i,this.constants,t),a.selectiveNotDeepExtend(["color"],this.constants.nodes,t.nodes),a.selectiveNotDeepExtend(["color","length"],this.constants.edges,t.edges),this.groups.useDefaultGroups=this.constants.useDefaultGroups,t.physics&&(a.mergeOptions(this.constants.physics,t.physics,"barnesHut"),a.mergeOptions(this.constants.physics,t.physics,"repulsion"),t.physics.hierarchicalRepulsion)){this.constants.hierarchicalLayout.enabled=!0,this.constants.physics.hierarchicalRepulsion.enabled=!0,this.constants.physics.barnesHut.enabled=!1;for(e in t.physics.hierarchicalRepulsion)t.physics.hierarchicalRepulsion.hasOwnProperty(e)&&(this.constants.physics.hierarchicalRepulsion[e]=t.physics.hierarchicalRepulsion[e])}if(t.onAdd&&(this.triggerFunctions.add=t.onAdd),t.onEdit&&(this.triggerFunctions.edit=t.onEdit),t.onEditEdge&&(this.triggerFunctions.editEdge=t.onEditEdge),t.onConnect&&(this.triggerFunctions.connect=t.onConnect),t.onDelete&&(this.triggerFunctions.del=t.onDelete),a.mergeOptions(this.constants,t,"smoothCurves"),a.mergeOptions(this.constants,t,"hierarchicalLayout"),a.mergeOptions(this.constants,t,"clustering"),a.mergeOptions(this.constants,t,"navigation"),a.mergeOptions(this.constants,t,"keyboard"),a.mergeOptions(this.constants,t,"dataManipulation"),t.dataManipulation&&(this.editMode=this.constants.dataManipulation.initiallyVisible),t.edges&&(void 0!==t.edges.color&&(a.isString(t.edges.color)?(this.constants.edges.color={},this.constants.edges.color.color=t.edges.color,this.constants.edges.color.highlight=t.edges.color,this.constants.edges.color.hover=t.edges.color):(void 0!==t.edges.color.color&&(this.constants.edges.color.color=t.edges.color.color),void 0!==t.edges.color.highlight&&(this.constants.edges.color.highlight=t.edges.color.highlight),void 0!==t.edges.color.hover&&(this.constants.edges.color.hover=t.edges.color.hover)),this.constants.edges.inheritColor=!1),t.edges.fontColor||void 0!==t.edges.color&&(a.isString(t.edges.color)?this.constants.edges.fontColor=t.edges.color:void 0!==t.edges.color.color&&(this.constants.edges.fontColor=t.edges.color.color))),t.nodes&&t.nodes.color){var s=a.parseColor(t.nodes.color);this.constants.nodes.color.background=s.background,this.constants.nodes.color.border=s.border,this.constants.nodes.color.highlight.background=s.highlight.background,this.constants.nodes.color.highlight.border=s.highlight.border,this.constants.nodes.color.hover.background=s.hover.background,this.constants.nodes.color.hover.border=s.hover.border}if(t.groups)for(var o in t.groups)if(t.groups.hasOwnProperty(o)){var n=t.groups[o];this.groups.add(o,n)}if(t.tooltip){for(e in t.tooltip)t.tooltip.hasOwnProperty(e)&&(this.constants.tooltip[e]=t.tooltip[e]);t.tooltip.color&&(this.constants.tooltip.color=a.parseColor(t.tooltip.color))}if("clickToUse"in t&&(t.clickToUse?this.activator||(this.activator=new b(this.frame),this.activator.on("change",this._createKeyBinds.bind(this))):this.activator&&(this.activator.destroy(),delete this.activator)),t.labels)throw new Error('Option "labels" is deprecated. Use options "locale" and "locales" instead.');this._loadPhysicsSystem(),this._loadNavigationControls(),this._loadManipulationSystem(),this._configureSmoothCurves(),this._bindHammer(),this._createKeyBinds(),this._markAllEdgesAsDirty(),this.setSize(this.constants.width,this.constants.height),this.moving=!0,1==this.constants.hierarchicalLayout.enabled&&0==this.initializing&&(this._resetLevels(),this._setupHierarchicalLayout()),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="vis network-frame",this.frame.style.position="relative",this.frame.style.overflow="hidden",this.frame.tabIndex=900,this.frame.canvas=document.createElement("canvas"),this.frame.canvas.style.position="relative",this.frame.appendChild(this.frame.canvas),this.frame.canvas.getContext){var t=this.frame.canvas.getContext("2d");this.pixelRatio=(window.devicePixelRatio||1)/(t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1),this.frame.canvas.getContext("2d").setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0)}else{var e=document.createElement("DIV");e.style.color="red",e.style.fontWeight="bold",e.style.padding="10px",e.innerHTML="Error: your browser does not support HTML canvas",this.frame.canvas.appendChild(e)}this._bindHammer()},s.prototype._bindHammer=function(){var t=this;void 0!==this.hammer&&this.hammer.dispose(),this.drag={},this.pinch={},this.hammer=n(this.frame.canvas,{prevent_default:!0}),this.hammer.on("tap",t._onTap.bind(t)),this.hammer.on("doubletap",t._onDoubleTap.bind(t)),this.hammer.on("hold",t._onHold.bind(t)),this.hammer.on("touch",t._onTouch.bind(t)),this.hammer.on("dragstart",t._onDragStart.bind(t)),this.hammer.on("drag",t._onDrag.bind(t)),this.hammer.on("dragend",t._onDragEnd.bind(t)),1==this.constants.zoomable&&(this.hammer.on("mousewheel",t._onMouseWheel.bind(t)),this.hammer.on("DOMMouseScroll",t._onMouseWheel.bind(t)),this.hammer.on("pinch",t._onPinch.bind(t))),this.hammer.on("mousemove",t._onMouseMoveTitle.bind(t)),this.hammerFrame=n(this.frame,{prevent_default:!0}),this.hammerFrame.on("release",t._onRelease.bind(t)),this.containerElement.appendChild(this.frame)},s.prototype._createKeyBinds=function(){var t=this;void 0!==this.keycharm&&this.keycharm.destroy(),this.keycharm=r(1==this.constants.keyboard.bindToWindow?{container:window,preventDefault:!1}:{container:this.frame,preventDefault:!1}),this.keycharm.reset(),this.constants.keyboard.enabled&&this.isActive()&&(this.keycharm.bind("up",this._moveUp.bind(t),"keydown"),this.keycharm.bind("up",this._yStopMoving.bind(t),"keyup"),this.keycharm.bind("down",this._moveDown.bind(t),"keydown"),this.keycharm.bind("down",this._yStopMoving.bind(t),"keyup"),this.keycharm.bind("left",this._moveLeft.bind(t),"keydown"),this.keycharm.bind("left",this._xStopMoving.bind(t),"keyup"),this.keycharm.bind("right",this._moveRight.bind(t),"keydown"),this.keycharm.bind("right",this._xStopMoving.bind(t),"keyup"),this.keycharm.bind("=",this._zoomIn.bind(t),"keydown"),this.keycharm.bind("=",this._stopZoom.bind(t),"keyup"),this.keycharm.bind("num+",this._zoomIn.bind(t),"keydown"),this.keycharm.bind("num+",this._stopZoom.bind(t),"keyup"),this.keycharm.bind("num-",this._zoomOut.bind(t),"keydown"),this.keycharm.bind("num-",this._stopZoom.bind(t),"keyup"),this.keycharm.bind("-",this._zoomOut.bind(t),"keydown"),this.keycharm.bind("-",this._stopZoom.bind(t),"keyup"),this.keycharm.bind("[",this._zoomIn.bind(t),"keydown"),this.keycharm.bind("[",this._stopZoom.bind(t),"keyup"),this.keycharm.bind("]",this._zoomOut.bind(t),"keydown"),this.keycharm.bind("]",this._stopZoom.bind(t),"keyup"),this.keycharm.bind("pageup",this._zoomIn.bind(t),"keydown"),this.keycharm.bind("pageup",this._stopZoom.bind(t),"keyup"),this.keycharm.bind("pagedown",this._zoomOut.bind(t),"keydown"),this.keycharm.bind("pagedown",this._stopZoom.bind(t),"keyup")),1==this.constants.dataManipulation.enabled&&(this.keycharm.bind("esc",this._createManipulatorBar.bind(t)),this.keycharm.bind("delete",this._deleteSelected.bind(t)))},s.prototype.destroy=function(){this.start=function(){},this.redraw=function(){},this.timer=!1,this._cleanupPhysicsConfiguration(),this.keycharm.reset(),this.hammer.dispose(),this.off(),this._recursiveDOMDelete(this.containerElement)},s.prototype._recursiveDOMDelete=function(t){for(;1==t.hasChildNodes();)this._recursiveDOMDelete(t.firstChild),t.removeChild(t.firstChild)},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){(new Date).valueOf()-this.touchTime>100&&(this.drag.pointer=this._getPointer(t.gesture.center),this.drag.pinched=!1,this.pinch.scale=this._getScale(),this.touchTime=(new Date).valueOf(),this._handleTouch(this.drag.pointer))},s.prototype._onDragStart=function(t){this._handleDragStart(t)},s.prototype._handleDragStart=function(t){void 0===this.drag.pointer&&this._onTouch(t);var e=this._getNodeAt(this.drag.pointer);if(this.drag.dragging=!0,this.drag.selection=[],this.drag.translation=this._getTranslation(),this.drag.nodeId=null,this.draggingNodes=!1,null!=e&&1==this.constants.dragNodes){this.draggingNodes=!0,this.drag.nodeId=e.id,e.isSelected()||this._selectObject(e,!1),this.emit("dragStart",{nodeIds:this.getSelection().nodes});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,this.drag.selection.push(o)}}},s.prototype._onDrag=function(t){this._handleOnDrag(t)},s.prototype._handleOnDrag=function(t){if(!this.drag.pinched){this.releaseNode();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){if(void 0===this.drag.pointer)return void this._handleDragStart(t);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(t){this._handleDragEnd(t)},s.prototype._handleDragEnd=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(),0==this.draggingNodes?this.emit("dragEnd",{nodeIds:[]}):this.emit("dragEnd",{nodeIds:this.getSelection().nodes})},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),s=!1;if(void 0!==this.popup&&(this.popup.hidden===!1&&this._checkHidePopup(i),this.popup.hidden===!1&&(s=!0,this.popup.setPosition(i.x+3,i.y-5),this.popup.show())),0==this.constants.keyboard.bindToWindow&&1==this.constants.keyboard.enabled&&this.frame.focus(),s===!1){var o=this,n=function(){o._checkShowPopup(i)};this.popupTimer&&clearInterval(this.popupTimer),this.drag.dragging||(this.popupTimer=setTimeout(n,this.constants.tooltip.delay))}if(1==this.constants.hover){for(var r in this.hoverObj.edges)this.hoverObj.edges.hasOwnProperty(r)&&(this.hoverObj.edges[r].hover=!1,delete this.hoverObj.edges[r]);var a=this._getNodeAt(i);null==a&&(a=this._getEdgeAt(i)),null!=a&&this._hoverObject(a);for(var d in this.hoverObj.nodes)this.hoverObj.nodes.hasOwnProperty(d)&&(a instanceof f&&a.id!=d||a instanceof g||null==a)&&(this._blurObject(this.hoverObj.nodes[d]),delete this.hoverObj.nodes[d]);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=void 0===this.popupObj?"":this.popupObj.id,o=!1,n="node";if(void 0==this.popupObj){var r=this.nodes,a=[];for(e in r)if(r.hasOwnProperty(e)){var h=r[e];h.isOverlappingWith(i)&&void 0!==h.getTitle()&&a.push(e)}a.length>0&&(this.popupObj=this.nodes[a[a.length-1]],o=!0)}if(void 0===this.popupObj&&0==o){var d=this.edges,l=[];for(e in d)if(d.hasOwnProperty(e)){var c=d[e];c.connected&&void 0!==c.getTitle()&&c.isOverlappingWith(i)&&l.push(e)}l.length>0&&(this.popupObj=this.edges[l[l.length-1]],n="edge")}this.popupObj?this.popupObj.id!=s&&(void 0===this.popup&&(this.popup=new v(this.frame,this.constants.tooltip)),this.popup.popupTargetType=n,this.popup.popupTargetId=this.popupObj.id,this.popup.setPosition(t.x+3,t.y-5),this.popup.setText(this.popupObj.getTitle()),this.popup.show()):this.popup&&this.popup.hide()},s.prototype._checkHidePopup=function(t){var e={left:this._XconvertDOMtoCanvas(t.x),top:this._YconvertDOMtoCanvas(t.y),right:this._XconvertDOMtoCanvas(t.x),bottom:this._YconvertDOMtoCanvas(t.y)},i=!1;if("node"==this.popup.popupTargetType){if(i=this.nodes[this.popup.popupTargetId].isOverlappingWith(e),i===!0){var s=this._getNodeAt(t);i=s.id==this.popup.popupTargetId}}else null===this._getNodeAt(t)&&(i=this.edges[this.popup.popupTargetId].isOverlappingWith(e));i===!1&&(this.popupObj=void 0,this.popup.hide())},s.prototype.setSize=function(t,e){var i=!1,s=this.frame.canvas.width,o=this.frame.canvas.height;t!=this.constants.width||e!=this.constants.height||this.frame.style.width!=t||this.frame.style.height!=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.pixelRatio,this.frame.canvas.height=this.frame.canvas.clientHeight*this.pixelRatio,this.constants.width=t,this.constants.height=e,i=!0):(this.frame.canvas.width!=this.frame.canvas.clientWidth*this.pixelRatio&&(this.frame.canvas.width=this.frame.canvas.clientWidth*this.pixelRatio,i=!0),this.frame.canvas.height!=this.frame.canvas.clientHeight*this.pixelRatio&&(this.frame.canvas.height=this.frame.canvas.clientHeight*this.pixelRatio,i=!0)),1==i&&this.emit("resize",{width:this.frame.canvas.width*this.pixelRatio,height:this.frame.canvas.height*this.pixelRatio,oldWidth:s*this.pixelRatio,oldHeight:o*this.pixelRatio})},s.prototype._setNodes=function(t){var e=this.nodesData;if(t instanceof d||t instanceof l)this.nodesData=t;else if(Array.isArray(t))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 f(o,this.images,this.groups,this.constants);if(this.nodes[e]=n,!(0!=n.xFixed&&0!=n.yFixed||null!==n.x&&null!==n.y)){var r=1*t.length+10,a=2*Math.PI*Math.random();0==n.xFixed&&(n.x=r*Math.cos(a)),0==n.yFixed&&(n.y=r*Math.sin(a))}this.moving=!0}this._updateNodeIndexList(),1==this.constants.hierarchicalLayout.enabled&&0==this.initializing&&(this._resetLevels(),this._setupHierarchicalLayout()),this._updateCalculationNodes(),this._reconnectEdges(),this._updateValueRange(this.nodes),this.updateLabels()},s.prototype._updateNodes=function(t,e){for(var i=this.nodes,s=0,o=t.length;o>s;s++){var n=t[s],r=i[n],a=e[s];r?r.setProperties(a,this.constants):(r=new f(properties,this.images,this.groups,this.constants),i[n]=r)}this.moving=!0,1==this.constants.hierarchicalLayout.enabled&&0==this.initializing&&(this._resetLevels(),this._setupHierarchicalLayout()),this._updateNodeIndexList(),this._updateValueRange(i),this._markAllEdgesAsDirty()},s.prototype._markAllEdgesAsDirty=function(){for(var t in this.edges)this.edges[t].colorDirty=!0},s.prototype._removeNodes=function(t){for(var e=this.nodes,i=0,s=t.length;s>i;i++)void 0!==this.selectionObj.nodes[t[i]]&&(this.nodes[t[i]].unselect(),this._removeFromSelection(this.nodes[t[i]]));for(var 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(Array.isArray(t))this.edgesData=new d,this.edgesData.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.edgesData=new d}if(e&&a.forEach(this.edgesListeners,function(t,i){e.off(i,t)}),this.edges={},this.edgesData){var i=this;a.forEach(this.edgesListeners,function(t,e){i.edgesData.on(e,t)});var s=this.edgesData.getIds();this._addEdges(s)}this._reconnectEdges()},s.prototype._addEdges=function(t){for(var e=this.edges,i=this.edgesData,s=0,o=t.length;o>s;s++){var n=t[s],r=e[n];r&&r.disconnect();var a=i.get(n,{showInternalIds:!0});e[n]=new g(a,this,this.constants)}this.moving=!0,this._updateValueRange(e),this._createBezierNodes(),this._updateCalculationNodes(),1==this.constants.hierarchicalLayout.enabled&&0==this.initializing&&(this._resetLevels(),this._setupHierarchicalLayout())},s.prototype._updateEdges=function(t){for(var e=this.edges,i=this.edgesData,s=0,o=t.length;o>s;s++){var n=t[s],r=i.get(n),a=e[n];a?(a.disconnect(),a.setProperties(r,this.constants),a.connect()):(a=new g(r,this,this.constants),this.edges[n]=a)}this._createBezierNodes(),1==this.constants.hierarchicalLayout.enabled&&0==this.initializing&&(this._resetLevels(),this._setupHierarchicalLayout()),this.moving=!0,this._updateValueRange(e)},s.prototype._removeEdges=function(t){for(var e=this.edges,i=0,s=t.length;s>i;i++)void 0!==this.selectionObj.edges[t[i]]&&(e[t[i]].unselect(),this._removeFromSelection(e[t[i]]));for(var 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=[],e[t].dynamicEdges=[]);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,o=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),o+=n)}if(void 0!==i&&void 0!==s)for(e in t)t.hasOwnProperty(e)&&t[e].setValueRange(i,s,o)},s.prototype.redraw=function(){this.setSize(this.constants.width,this.constants.height),this._redraw()},s.prototype._requestRedraw=function(t){this.redrawRequested!==!0&&(this.redrawRequested=!0,this.requiresTimeout===!0?window.setTimeout(this._redraw.bind(this,t),0):window.requestAnimationFrame(this._redraw.bind(this,t,!0)))},s.prototype._redraw=function(t){void 0===t&&(t=!1),this.redrawRequested=!1;var e=this.frame.canvas.getContext("2d");e.setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0);var i=this.frame.canvas.clientWidth,s=this.frame.canvas.clientHeight;e.clearRect(0,0,i,s),e.save(),e.translate(this.translation.x,this.translation.y),e.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)},t===!1&&(this._doInAllSectors("_drawAllSectorNodes",e),(0==this.drag.dragging||void 0===this.drag.dragging||0==this.constants.hideEdgesOnDrag)&&this._doInAllSectors("_drawEdges",e)),(0==this.drag.dragging||void 0===this.drag.dragging||0==this.constants.hideNodesOnDrag)&&this._doInAllSectors("_drawNodes",e,!1),t===!1&&1==this.controlNodesActive&&this._doInAllSectors("_drawControlNodes",e),e.restore(),t===!0&&e.clearRect(0,0,i,s)},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);return o>.5*this.constants.maxVelocity?!0:this._isMoving(o)}return!1},s.prototype._revertPhysicsState=function(){var t=this.nodes;for(var e in t)t.hasOwnProperty(e)&&t[e].revertPosition()},s.prototype._revertPhysicsTick=function(){this._doInAllActiveSectors("_revertPhysicsState"),1==this.constants.smoothCurves.enabled&&1==this.constants.smoothCurves.dynamic&&this._doInSupportSector("_revertPhysicsState")},s.prototype._physicsTick=function(){if(!this.freezeSimulationEnabled&&1==this.moving){var t=!1,e=!1;this._doInAllActiveSectors("_initializeForceCalculation");var i=this._doInAllActiveSectors("_discreteStepNodes");1==this.constants.smoothCurves.enabled&&1==this.constants.smoothCurves.dynamic&&(e=this._doInSupportSector("_discreteStepNodes"));for(var s=0;s2*e||1==this.runDoubleSpeed)&&1==this.moving&&(this._physicsTick(),0!=this.renderTime&&(this.runDoubleSpeed=!0))}var i=Date.now();this._redraw(),this.renderTime=Date.now()-i,0==this.requiresTimeout&&this.start()},"undefined"!=typeof window&&(window.requestAnimationFrame=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame),s.prototype.start=function(){if(1==this.freezeSimulationEnabled&&(this.moving=!1),1==this.moving||0!=this.xIncrement||0!=this.yIncrement||0!=this.zoomIncrement||1==this.animating)this.timer||(this.timer=1==this.requiresTimeout?window.setTimeout(this._animationStep.bind(this),this.renderTimestep):window.requestAnimationFrame(this._animationStep.bind(this)));else if(this._requestRedraw(),this.stabilizationIterations>1){var t=this,e={iterations:t.stabilizationIterations};this.stabilizationIterations=0,this.startedStabilization=!1,setTimeout(function(){t.emit("stabilized",e)},0)}else this.stabilizationIterations=0},s.prototype._handleNavigation=function(){if(0!=this.xIncrement||0!=this.yIncrement){var t=this._getTranslation();this._setTranslation(t.x+this.xIncrement,t.y+this.yIncrement)}if(0!=this.zoomIncrement){var e={x:this.frame.canvas.clientWidth/2,y:this.frame.canvas.clientHeight/2};this._zoom(this.scale*(1+this.zoomIncrement),e)}},s.prototype.freezeSimulation=function(t){1==t?(this.freezeSimulationEnabled=!0,this.moving=!1):(this.freezeSimulationEnabled=!1,this.moving=!0,this.start())},s.prototype._configureSmoothCurves=function(t){if(void 0===t&&(t=!0),1==this.constants.smoothCurves.enabled&&1==this.constants.smoothCurves.dynamic){this._createBezierNodes();for(var e in this.sectors.support.nodes)this.sectors.support.nodes.hasOwnProperty(e)&&void 0===this.edges[this.sectors.support.nodes[e].parentEdgeId]&&delete this.sectors.support.nodes[e]}else{this.sectors.support.nodes={};for(var i in this.edges)this.edges.hasOwnProperty(i)&&(this.edges[i].via=null)}this._updateCalculationNodes(),t||(this.moving=!0,this.start())},s.prototype._createBezierNodes=function(){if(1==this.constants.smoothCurves.enabled&&1==this.constants.smoothCurves.dynamic)for(var t in this.edges)if(this.edges.hasOwnProperty(t)){var e=this.edges[t];if(null==e.via){var i="edgeId:".concat(e.id);this.sectors.support.nodes[i]=new f({id:i,mass:1,shape:"circle",image:"",internalMultiplier:1},{},{},this.constants),e.via=this.sectors.support.nodes[i],e.via.parentEdgeId=e.id,e.positionBezierNode()}}},s.prototype._initializeMixinLoaders=function(){for(var t in y)y.hasOwnProperty(t)&&(s.prototype[t]=y[t])},s.prototype.storePosition=function(){console.log("storePosition is depricated: use .storePositions() from now on."),this.storePositions()},s.prototype.storePositions=function(){var t=[];for(var e in this.nodes)if(this.nodes.hasOwnProperty(e)){var i=this.nodes[e],s=!this.nodes.xFixed,o=!this.nodes.yFixed;(this.nodesData._data[e].x!=Math.round(i.x)||this.nodesData._data[e].y!=Math.round(i.y))&&t.push({id:e,x:Math.round(i.x),y:Math.round(i.y),allowedToMoveX:s,allowedToMoveY:o})}this.nodesData.update(t)},s.prototype.getPositions=function(t){var e={};if(void 0!==t){if(1==Array.isArray(t)){for(var i=0;i=1&&(this.animating=!1,this.easingTime=0,this._redraw=null!=this.lockedOnNodeId?this._lockedRedraw:this._classicRedraw,this.emit("animationFinished"))},s.prototype._classicRedraw=function(){},s.prototype.isActive=function(){return!this.activator||this.activator.active},s.prototype.setScale=function(){return this._setScale()},s.prototype.getScale=function(){return this._getScale()},s.prototype.getCenterCoordinates=function(){return this.DOMtoCanvas({x:.5*this.frame.canvas.clientWidth,y:.5*this.frame.canvas.clientHeight})},s.prototype.getBoundingBox=function(t){return void 0!==this.nodes[t]?this.nodes[t].boundingBox:void 0},s.prototype.getConnectedNodes=function(t){var e=[];if(void 0!==this.nodes[t])for(var i=this.nodes[t],s={nodeId:!0},o=0;oh}return!1},s.prototype._getColor=function(t){var e=this.options.color;if(1==this.options.useGradients){var i,s,n=t.createLinearGradient(this.from.x,this.from.y,this.to.x,this.to.y);return i=this.from.options.color.highlight.border,s=this.to.options.color.highlight.border,0==this.from.selected&&0==this.to.selected?(i=o.overrideOpacity(this.from.options.color.border,this.options.opacity),s=o.overrideOpacity(this.to.options.color.border,this.options.opacity)):1==this.from.selected&&0==this.to.selected?s=this.to.options.color.border:0==this.from.selected&&1==this.to.selected&&(i=this.from.options.color.border),n.addColorStop(0,i),n.addColorStop(1,s),n}return this.colorDirty===!0&&("to"==this.options.inheritColor?e={highlight:this.to.options.color.highlight.border,hover:this.to.options.color.hover.border,color:o.overrideOpacity(this.from.options.color.border,this.options.opacity)}:("from"==this.options.inheritColor||1==this.options.inheritColor)&&(e={highlight:this.from.options.color.highlight.border,hover:this.from.options.color.hover.border,color:o.overrideOpacity(this.from.options.color.border,this.options.opacity)}),this.options.color=e,this.colorDirty=!1),1==this.selected?e.highlight:1==this.hover?e.hover:e.color},s.prototype._drawLine=function(t){if(t.strokeStyle=this._getColor(t),t.lineWidth=this._getLineWidth(),this.from!=this.to){var e,i=this._line(t);if(this.label){if(1==this.options.smoothCurves.enabled&&null!=i){var s=.5*(.5*(this.from.x+i.x)+.5*(this.to.x+i.x)),o=.5*(.5*(this.from.y+i.y)+.5*(this.to.y+i.y));e={x:s,y:o}}else e=this._pointOnLine(.5);this._label(t,this.label,e.x,e.y)}}else{var n,r,a=this.physics.springLength/4,h=this.from;h.width||h.resize(t),h.width>h.height?(n=h.x+h.width/2,r=h.y-a):(n=h.x+a,r=h.y-h.height/2),this._circle(t,n,r,a),e=this._pointOnCircle(n,r,a,.5),this._label(t,this.label,e.x,e.y)}},s.prototype._getLineWidth=function(){return 1==this.selected?Math.max(Math.min(this.widthSelected,this.options.widthMax),.3*this.networkScaleInv):1==this.hover?Math.max(Math.min(this.options.hoverWidth,this.options.widthMax),.3*this.networkScaleInv):Math.max(this.options.width,.3*this.networkScaleInv)},s.prototype._getViaCoordinates=function(){if(1==this.options.smoothCurves.dynamic&&1==this.options.smoothCurves.enabled)return this.via;if(0==this.options.smoothCurves.enabled)return{x:0,y:0};var t=null,e=null,i=this.options.smoothCurves.roundness,s=this.options.smoothCurves.type,o=Math.abs(this.from.x-this.to.x),n=Math.abs(this.from.y-this.to.y);if("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));else if("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.yd;d++){var l=t.measureText(n[d]).width;h=l>h?l:h}var c=this.options.fontSize*r,p=i-h/2,u=s-c/2;this.labelDimensions={top:u,left:p,width:h,height:c,yLine:o}}var o=this.labelDimensions.yLine;t.save(),"horizontal"!=this.options.labelAlignment&&(t.translate(i,o),this._rotateForLabelAlignment(t),i=0,o=0),this._drawLabelRect(t),this._drawLabelText(t,i,o,n,r,a),t.restore()}},s.prototype._rotateForLabelAlignment=function(t){var e=this.from.y-this.to.y,i=this.from.x-this.to.x,s=Math.atan2(e,i);(-1>s&&0>i||s>0&&0>i)&&(s+=Math.PI),t.rotate(s)},s.prototype._drawLabelRect=function(t){if(void 0!==this.options.fontFill&&null!==this.options.fontFill&&"none"!==this.options.fontFill){t.fillStyle=this.options.fontFill;var e=2;"line-center"==this.options.labelAlignment?t.fillRect(.5*-this.labelDimensions.width,.5*-this.labelDimensions.height,this.labelDimensions.width,this.labelDimensions.height):"line-above"==this.options.labelAlignment?t.fillRect(.5*-this.labelDimensions.width,-(this.labelDimensions.height+e),this.labelDimensions.width,this.labelDimensions.height):"line-below"==this.options.labelAlignment?t.fillRect(.5*-this.labelDimensions.width,e,this.labelDimensions.width,this.labelDimensions.height):t.fillRect(this.labelDimensions.left,this.labelDimensions.top,this.labelDimensions.width,this.labelDimensions.height)}},s.prototype._drawLabelText=function(t,e,i,s,o,n){if(t.fillStyle=this.options.fontColor||"black",t.textAlign="center","horizontal"!=this.options.labelAlignment){var r=2;"line-above"==this.options.labelAlignment?(t.textBaseline="alphabetic",i-=2*r):"line-below"==this.options.labelAlignment?(t.textBaseline="hanging",i+=2*r):t.textBaseline="middle"}else t.textBaseline="middle";this.options.fontStrokeWidth>0&&(t.lineWidth=this.options.fontStrokeWidth,t.strokeStyle=this.options.fontStrokeColor,t.lineJoin="round");for(var a=0;o>a;a++)this.options.fontStrokeWidth>0&&t.strokeText(s[a],e,i),t.fillText(s[a],e,i),i+=n},s.prototype._drawDashLine=function(t){t.strokeStyle=this._getColor(t),t.lineWidth=this._getLineWidth();var e=null;if(void 0!==t.setLineDash){t.save();var i=[0];i=void 0!==this.options.dash.length&&void 0!==this.options.dash.gap?[this.options.dash.length,this.options.dash.gap]:[5,5],t.setLineDash(i),t.lineDashOffset=0,e=this._line(t),t.setLineDash([0]),t.lineDashOffset=0,t.restore()}else t.beginPath(),t.lineCap="round",void 0!==this.options.dash.altLength?t.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y,[this.options.dash.length,this.options.dash.gap,this.options.dash.altLength,this.options.dash.gap]):void 0!==this.options.dash.length&&void 0!==this.options.dash.gap?t.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y,[this.options.dash.length,this.options.dash.gap]):(t.moveTo(this.from.x,this.from.y),t.lineTo(this.to.x,this.to.y)),t.stroke();if(this.label){var s;if(1==this.options.smoothCurves.enabled&&null!=e){var o=.5*(.5*(this.from.x+e.x)+.5*(this.to.x+e.x)),n=.5*(.5*(this.from.y+e.y)+.5*(this.to.y+e.y));s={x:o,y:n}}else s=this._pointOnLine(.5);this._label(t,this.label,s.x,s.y)}},s.prototype._pointOnLine=function(t){return{x:(1-t)*this.from.x+t*this.to.x,y:(1-t)*this.from.y+t*this.to.y}},s.prototype._pointOnCircle=function(t,e,i,s){var o=2*(s-3/8)*Math.PI;return{x:t+i*Math.cos(o),y:e-i*Math.sin(o)}},s.prototype._drawArrowCenter=function(t){var e;if(t.strokeStyle=this._getColor(t),t.fillStyle=t.strokeStyle,t.lineWidth=this._getLineWidth(),this.from!=this.to){var i=this._line(t),s=Math.atan2(this.to.y-this.from.y,this.to.x-this.from.x),o=(10+5*this.options.width)*this.options.arrowScaleFactor;if(1==this.options.smoothCurves.enabled&&null!=i){var n=.5*(.5*(this.from.x+i.x)+.5*(this.to.x+i.x)),r=.5*(.5*(this.from.y+i.y)+.5*(this.to.y+i.y));e={x:n,y:r}}else e=this._pointOnLine(.5);t.arrow(e.x,e.y,s,o),t.fill(),t.stroke(),this.label&&this._label(t,this.label,e.x,e.y)}else{var a,h,d=.25*Math.max(100,this.physics.springLength),l=this.from;l.width||l.resize(t),l.width>l.height?(a=l.x+.5*l.width,h=l.y-d):(a=l.x+d,h=l.y-.5*l.height),this._circle(t,a,h,d);var s=.2*Math.PI,o=(10+5*this.options.width)*this.options.arrowScaleFactor;e=this._pointOnCircle(a,h,d,.5),t.arrow(e.x,e.y,s,o),t.fill(),t.stroke(),this.label&&(e=this._pointOnCircle(a,h,d,.5),this._label(t,this.label,e.x,e.y))}},s.prototype._pointOnBezier=function(t){var e=this._getViaCoordinates(),i=Math.pow(1-t,2)*this.from.x+2*t*(1-t)*e.x+Math.pow(t,2)*this.to.x,s=Math.pow(1-t,2)*this.from.y+2*t*(1-t)*e.y+Math.pow(t,2)*this.to.y;return{x:i,y:s}},s.prototype._findBorderPosition=function(t,e){var i,s,o,n,r,a=10,h=0,d=0,l=1,c=.2,p=this.to;for(1==t&&(p=this.from);l>=d&&a>h;){var u=.5*(d+l);if(i=this._pointOnBezier(u),s=Math.atan2(p.y-i.y,p.x-i.x),o=p.distanceToBorder(e,s),n=Math.sqrt(Math.pow(i.x-p.x,2)+Math.pow(i.y-p.y,2)),r=o-n,Math.abs(r)r?0==t?d=u:l=u:0==t?l=u:d=u,h++}return i.t=u,i},s.prototype._drawArrow=function(t){t.strokeStyle=this._getColor(t),t.fillStyle=t.strokeStyle,t.lineWidth=this._getLineWidth();var e,i,s;if(this.from!=this.to){if(this._line(t),1==this.options.smoothCurves.enabled){var o=this._getViaCoordinates();s=this._findBorderPosition(!1,t);var n=this._pointOnBezier(Math.max(0,s.t-.1));e=Math.atan2(s.y-n.y,s.x-n.x)}else{e=Math.atan2(this.to.y-this.from.y,this.to.x-this.from.x);var r=this.to.x-this.from.x,a=this.to.y-this.from.y,h=Math.sqrt(r*r+a*a),d=this.to.distanceToBorder(t,e),l=(h-d)/h;s={},s.x=(1-l)*this.from.x+l*this.to.x,s.y=(1-l)*this.from.y+l*this.to.y}if(i=(10+5*this.options.width)*this.options.arrowScaleFactor,t.arrow(s.x,s.y,e,i),t.fill(),t.stroke(),this.label){var c;c=1==this.options.smoothCurves.enabled&&null!=o?this._pointOnBezier(.5):this._pointOnLine(.5),this._label(t,this.label,c.x,c.y)}}else{var p,u,m,f=this.from,g=.25*Math.max(100,this.physics.springLength);f.width||f.resize(t),f.width>f.height?(p=f.x+.5*f.width,u=f.y-g,m={x:p,y:f.y,angle:.9*Math.PI}):(p=f.x+g,u=f.y-.5*f.height,m={x:f.x,y:u,angle:.6*Math.PI}),t.beginPath(),t.arc(p,u,g,0,2*Math.PI,!1),t.stroke();var i=(10+5*this.options.width)*this.options.arrowScaleFactor;t.arrow(m.x,m.y,m.angle,i),t.fill(),t.stroke(),this.label&&(c=this._pointOnCircle(p,u,g,.5),this._label(t,this.label,c.x,c.y))}},s.prototype._getDistanceToEdge=function(t,e,i,s,o,n){var r=0;if(this.from!=this.to)if(1==this.options.smoothCurves.enabled){var a,h;if(1==this.options.smoothCurves.enabled&&1==this.options.smoothCurves.dynamic)a=this.via.x,h=this.via.y;else{var d=this._getViaCoordinates();a=d.x,h=d.y}var l,c,p,u,m,f,g,v=1e9;for(c=0;10>c;c++)p=.1*c,u=Math.pow(1-p,2)*t+2*p*(1-p)*a+Math.pow(p,2)*i,m=Math.pow(1-p,2)*e+2*p*(1-p)*h+Math.pow(p,2)*s,c>0&&(l=this._getDistanceToLine(f,g,u,m,o,n),v=v>l?l:v),f=u,g=m;r=v}else r=this._getDistanceToLine(t,e,i,s,o,n);else{var u,m,y,b,_=.25*this.physics.springLength,x=this.from;x.width>x.height?(u=x.x+.5*x.width,m=x.y-_):(u=x.x+_,m=x.y-.5*x.height),y=u-o,b=m-n,r=Math.abs(Math.sqrt(y*y+b*b)-_)}return this.labelDimensions.lefto&&this.labelDimensions.topn?0:r},s.prototype._getDistanceToLine=function(t,e,i,s,o,n){var r=i-t,a=s-e,h=r*r+a*a,d=((o-t)*r+(n-e)*a)/h;d>1?d=1:0>d&&(d=0);var l=t+d*r,c=e+d*a,p=l-o,u=c-n;return Math.sqrt(p*p+u*u)},s.prototype.setScale=function(t){this.networkScaleInv=1/t},s.prototype.select=function(){this.selected=!0},s.prototype.unselect=function(){this.selected=!1},s.prototype.positionBezierNode=function(){null!==this.via&&null!==this.from&&null!==this.to?(this.via.x=.5*(this.from.x+this.to.x),this.via.y=.5*(this.from.y+this.to.y)):null!==this.via&&(this.via.x=0,this.via.y=0)},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:7,borderWidth:2,borderWidthSelected:2},physics:{damping:0},clustering:{maxNodeSizeIncrements:0,nodeScaling:{width:0,height:0,radius:0}}};this.controlNodes.from=new n({id:e,shape:"dot",color:{background:"#ff0000",border:"#3c3c3c",highlight:{background:"#07f968"}}},{},{},s),this.controlNodes.to=new n({id:i,shape:"dot",color:{background:"#ff0000",border:"#3c3c3c",highlight:{background:"#07f968"}}},{},{},s)}this.controlNodes.positions={},0==this.controlNodes.from.selected&&(this.controlNodes.positions.from=this.getControlNodeFromPosition(t),this.controlNodes.from.x=this.controlNodes.positions.from.x,this.controlNodes.from.y=this.controlNodes.positions.from.y),0==this.controlNodes.to.selected&&(this.controlNodes.positions.to=this.getControlNodeToPosition(t),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.fromBackup=this.from,this.toBackup=this.to,this.controlNodesEnabled=!0},s.prototype._disableControlNodes=function(){this.fromId=this.from.id,this.toId=this.to.id,this.fromId!=this.fromBackup.id?this.fromBackup.detachEdge(this):this.toId!=this.toBackup.id&&this.toBackup.detachEdge(this),this.fromBackup=null,this.toBackup=null,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.getControlNodeFromPosition=function(t){var e;if(1==this.options.smoothCurves.enabled)e=this._findBorderPosition(!0,t);else{var 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;e={},e.x=a*this.from.x+(1-a)*this.to.x,e.y=a*this.from.y+(1-a)*this.to.y}return e},s.prototype.getControlNodeToPosition=function(t){var e;if(1==this.options.smoothCurves.enabled)e=this._findBorderPosition(!1,t);else{var 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.to.distanceToBorder(t,i),a=(n-r)/n;e={},e.x=(1-a)*this.from.x+a*this.to.x,e.y=(1-a)*this.from.y+a*this.to.y}return e},t.exports=s},function(t,e,i){function s(t,e,i,s){var n=o.selectiveBridgeObject(["nodes"],s);this.options=n.nodes,this.selected=!1,this.hover=!1,this.edges=[],this.dynamicEdges=[],this.reroutedEdges={},this.id=void 0,this.allowedToMoveX=!1,this.allowedToMoveY=!1,this.xFixed=!1,this.yFixed=!1,this.horizontalAlignLeft=!0,this.verticalAlignTop=!0,this.baseRadiusValue=s.nodes.radius,this.radiusFixed=!1,this.level=-1,this.preassignedLevel=!1,this.hierarchyEnumerated=!1,this.labelDimensions={top:0,left:0,width:0,height:0,yLine:0},this.boundingBox={top:0,left:0,right:0,bottom:0},this.imagelist=e,this.grouplist=i,this.fx=0,this.fy=0,this.vx=0,this.vy=0,this.x=null,this.y=null,this.predefinedPosition=!1,this.previousState={vx:0,vy:0,x:0,y:0},this.damping=s.physics.damping,this.fixedData={x:null,y:null},this.setProperties(t,n),this.resetCluster(),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.revertPosition=function(){this.x=this.previousState.x,this.y=this.previousState.y,this.vx=this.previousState.vx,this.vy=this.previousState.vy},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)},s.prototype.detachEdge=function(t){var e=this.edges.indexOf(t);-1!=e&&this.edges.splice(e,1),e=this.dynamicEdges.indexOf(t),-1!=e&&this.dynamicEdges.splice(e,1)},s.prototype.setProperties=function(t,e){if(t){var i=["borderWidth","borderWidthSelected","shape","image","brokenImage","radius","fontColor","fontSize","fontFace","fontFill","fontStrokeWidth","fontStrokeColor","group","mass","fontDrawThreshold","scaleFontWithValue","fontSizeMaxVisible","customScalingFunction","iconFontFace","icon","iconColor","iconSize"];if(o.selectiveDeepExtend(i,this.options,t),void 0!==t.id&&(this.id=t.id),void 0!==t.label&&(this.label=t.label,this.originalLabel=t.label),void 0!==t.title&&(this.title=t.title),void 0!==t.x&&(this.x=t.x,this.predefinedPosition=!0),void 0!==t.y&&(this.y=t.y,this.predefinedPosition=!0),void 0!==t.value&&(this.value=t.value),void 0!==t.level&&(this.level=t.level,this.preassignedLevel=!0),void 0!==t.horizontalAlignLeft&&(this.horizontalAlignLeft=t.horizontalAlignLeft),void 0!==t.verticalAlignTop&&(this.verticalAlignTop=t.verticalAlignTop),void 0!==t.triggerFunction&&(this.triggerFunction=t.triggerFunction),void 0===this.id)throw"Node must have an id";if("number"==typeof t.group||"string"==typeof t.group&&""!=t.group){var s=this.grouplist.get(t.group);o.deepExtend(this.options,s),this.options.color=o.parseColor(this.options.color)}if(void 0!==t.radius&&(this.baseRadiusValue=this.options.radius),void 0!==t.color&&(this.options.color=o.parseColor(t.color)),void 0!==this.options.image&&""!=this.options.image){if(!this.imagelist)throw"No imagelist provided";this.imageObj=this.imagelist.load(this.options.image,this.options.brokenImage)}switch(void 0!==t.allowedToMoveX?(this.xFixed=!t.allowedToMoveX,this.allowedToMoveX=t.allowedToMoveX):void 0!==t.x&&0==this.allowedToMoveX&&(this.xFixed=!0),void 0!==t.allowedToMoveY?(this.yFixed=!t.allowedToMoveY,this.allowedToMoveY=t.allowedToMoveY):void 0!==t.y&&0==this.allowedToMoveY&&(this.yFixed=!0),this.radiusFixed=this.radiusFixed||void 0!==t.radius,("image"===this.options.shape||"circularImage"===this.options.shape)&&(this.options.radiusMin=e.nodes.widthMin,this.options.radiusMax=e.nodes.widthMax),this.options.shape){case"database":this.draw=this._drawDatabase,this.resize=this._resizeDatabase;break;case"box":this.draw=this._drawBox,this.resize=this._resizeBox;break;case"circle":this.draw=this._drawCircle,this.resize=this._resizeCircle;break;case"ellipse":this.draw=this._drawEllipse,this.resize=this._resizeEllipse;break;case"image":this.draw=this._drawImage,this.resize=this._resizeImage;break;case"circularImage":this.draw=this._drawCircularImage,this.resize=this._resizeCircularImage;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;case"icon":this.draw=this._drawIcon,this.resize=this._resizeIcon;break;default:this.draw=this._drawEllipse,this.resize=this._resizeEllipse}this._reset()}},s.prototype.select=function(){this.selected=!0,this._reset()},s.prototype.unselect=function(){this.selected=!1,this._reset()},s.prototype.clearSizeCache=function(){this._reset()},s.prototype._reset=function(){this.width=void 0,this.height=void 0},s.prototype.getTitle=function(){return"function"==typeof this.title?this.title():this.title},s.prototype.distanceToBorder=function(t,e){var i=1;switch(this.width||this.resize(t),this.options.shape){case"circle":case"dot":return this.options.radius+i;case"ellipse":var s=this.width/2,o=this.height/2,n=Math.sin(e)*s,r=Math.cos(e)*o;return s*o/Math.sqrt(n*n+r*r);case"box":case"image":case"text":default:return this.width?Math.min(Math.abs(this.width/2/Math.cos(e)),Math.abs(this.height/2/Math.sin(e)))+i:0}},s.prototype._setForce=function(t,e){this.fx=t,this.fy=e},s.prototype._addForce=function(t,e){this.fx+=t,this.fy+=e},s.prototype.storeState=function(){this.previousState.x=this.x,this.previousState.y=this.y,this.previousState.vx=this.vx,this.previousState.vy=this.vy},s.prototype.discreteStep=function(t){if(this.storeState(),this.xFixed)this.fx=0,this.vx=0;else{var e=this.damping*this.vx,i=(this.fx-e)/this.options.mass;this.vx+=i*t,this.x+=this.vx*t}if(this.yFixed)this.fy=0,this.vy=0;else{var s=this.damping*this.vy,o=(this.fy-s)/this.options.mass;this.vy+=o*t,this.y+=this.vy*t}},s.prototype.discreteStepLimited=function(t,e){if(this.storeState(),this.xFixed)this.fx=0,this.vx=0;else{var i=this.damping*this.vx,s=(this.fx-i)/this.options.mass;this.vx+=s*t,this.vx=Math.abs(this.vx)>e?this.vx>0?e:-e:this.vx,this.x+=this.vx*t}if(this.yFixed)this.fy=0,this.vy=0;else{var o=this.damping*this.vy,n=(this.fy-o)/this.options.mass;this.vy+=n*t,this.vy=Math.abs(this.vy)>e?this.vy>0?e:-e:this.vy,this.y+=this.vy*t}},s.prototype.isFixed=function(){return this.xFixed&&this.yFixed},s.prototype.isMoving=function(t){var e=Math.sqrt(Math.pow(this.vx,2)+Math.pow(this.vy,2));return e>t},s.prototype.isSelected=function(){return this.selected},s.prototype.getValue=function(){return this.value},s.prototype.getDistance=function(t,e){var i=this.x-t,s=this.y-e;return Math.sqrt(i*i+s*s)},s.prototype.setValueRange=function(t,e,i){if(!this.radiusFixed&&void 0!==this.value){var s=this.options.customScalingFunction(t,e,i,this.value),o=this.options.radiusMax-this.options.radiusMin;if(1==this.options.scaleFontWithValue){var n=this.options.fontSizeMax-this.options.fontSizeMin;this.options.fontSize=this.options.fontSizeMin+s*n}this.options.radius=this.options.radiusMin+s*o}this.baseRadiusValue=this.options.radius},s.prototype.draw=function(){throw"Draw method not initialized for node"},s.prototype.resize=function(){throw"Resize method not initialized for node"},s.prototype.isOverlappingWith=function(t){return this.leftt.left&&this.topt.top},s.prototype._resizeImage=function(){if(!this.width||!this.height){var t,e;if(this.value){this.options.radius=this.baseRadiusValue;var i=this.imageObj.height/this.imageObj.width;void 0!==i?(t=this.options.radius||this.imageObj.width,e=this.options.radius*i||this.imageObj.height):(t=0,e=0)}else t=this.imageObj.width,e=this.imageObj.height;this.width=t,this.height=e,this.growthIndicator=0,this.width>0&&this.height>0&&(this.width+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeWidthFactor,this.height+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeHeightFactor,this.options.radius+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeRadiusFactor,this.growthIndicator=this.width-t)}},s.prototype._drawImageAtPosition=function(t){if(0!=this.imageObj.width){if(this.clusterSize>1){var e=this.clusterSize>1?10:0;e*=this.networkScaleInv,e=Math.min(.2*this.width,e),t.globalAlpha=.5,t.drawImage(this.imageObj,this.left-e,this.top-e,this.width+2*e,this.height+2*e)}t.globalAlpha=1,t.drawImage(this.imageObj,this.left,this.top,this.width,this.height)}},s.prototype._drawImageLabel=function(t){var e,i=0;if(this.height){i=this.height/2;var s=this.getTextSize(t);s.lineCount>=1&&(i+=s.height/2,i+=3)}e=this.y+i,this._label(t,this.label,this.x,e,void 0)},s.prototype._drawImage=function(t){this._resizeImage(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,this._drawImageAtPosition(t),this.boundingBox.top=this.top,this.boundingBox.left=this.left,this.boundingBox.right=this.left+this.width,this.boundingBox.bottom=this.top+this.height,this._drawImageLabel(t),this.boundingBox.left=Math.min(this.boundingBox.left,this.labelDimensions.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelDimensions.left+this.labelDimensions.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelDimensions.height)},s.prototype._resizeCircularImage=function(t){if(this.imageObj.src&&this.imageObj.width&&this.imageObj.height)this._swapToImageResizeWhenImageLoaded&&(this.width=0,this.height=0,delete this._swapToImageResizeWhenImageLoaded),this._resizeImage(t);else if(!this.width){var e=2*this.options.radius;this.width=e,this.height=e,this.options.radius+=.5*Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeRadiusFactor,this.growthIndicator=this.options.radius-.5*e,this._swapToImageResizeWhenImageLoaded=!0}},s.prototype._drawCircularImage=function(t){this._resizeCircularImage(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2;var e=this.left+this.width/2,i=this.top+this.height/2,s=Math.abs(this.height/2);this._drawRawCircle(t,e,i,s),t.save(),t.circle(this.x,this.y,s),t.stroke(),t.clip(),this._drawImageAtPosition(t),t.restore(),this.boundingBox.top=this.y-this.options.radius,this.boundingBox.left=this.x-this.options.radius,this.boundingBox.right=this.x+this.options.radius,this.boundingBox.bottom=this.y+this.options.radius,this._drawImageLabel(t),this.boundingBox.left=Math.min(this.boundingBox.left,this.labelDimensions.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelDimensions.left+this.labelDimensions.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelDimensions.height)},s.prototype._resizeBox=function(t){if(!this.width){var e=5,i=this.getTextSize(t);this.width=i.width+2*e,this.height=i.height+2*e,this.width+=.5*Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeWidthFactor,this.height+=.5*Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeHeightFactor,this.growthIndicator=this.width-(i.width+2*e)}},s.prototype._drawBox=function(t){this._resizeBox(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2;var e=2.5,i=this.options.borderWidth,s=this.options.borderWidthSelected||2*this.options.borderWidth;t.strokeStyle=this.selected?this.options.color.highlight.border:this.hover?this.options.color.hover.border:this.options.color.border,this.clusterSize>1&&(t.lineWidth=(this.selected?s:i)+(this.clusterSize>1?e:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.roundRect(this.left-2*t.lineWidth,this.top-2*t.lineWidth,this.width+4*t.lineWidth,this.height+4*t.lineWidth,this.options.radius),t.stroke()),t.lineWidth=(this.selected?s:i)+(this.clusterSize>1?e:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.fillStyle=this.selected?this.options.color.highlight.background:this.hover?this.options.color.hover.background:this.options.color.background,t.roundRect(this.left,this.top,this.width,this.height,this.options.radius),t.fill(),t.stroke(),this.boundingBox.top=this.top,this.boundingBox.left=this.left,this.boundingBox.right=this.left+this.width,this.boundingBox.bottom=this.top+this.height,this._label(t,this.label,this.x,this.y)},s.prototype._resizeDatabase=function(t){if(!this.width){var e=5,i=this.getTextSize(t),s=i.width+2*e;this.width=s,this.height=s,this.width+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeWidthFactor,this.height+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeHeightFactor,this.options.radius+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeRadiusFactor,this.growthIndicator=this.width-s}},s.prototype._drawDatabase=function(t){this._resizeDatabase(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2;var e=2.5,i=this.options.borderWidth,s=this.options.borderWidthSelected||2*this.options.borderWidth;t.strokeStyle=this.selected?this.options.color.highlight.border:this.hover?this.options.color.hover.border:this.options.color.border,this.clusterSize>1&&(t.lineWidth=(this.selected?s:i)+(this.clusterSize>1?e:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.database(this.x-this.width/2-2*t.lineWidth,this.y-.5*this.height-2*t.lineWidth,this.width+4*t.lineWidth,this.height+4*t.lineWidth),t.stroke()),t.lineWidth=(this.selected?s:i)+(this.clusterSize>1?e:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.fillStyle=this.selected?this.options.color.highlight.background:this.hover?this.options.color.hover.background:this.options.color.background,t.database(this.x-this.width/2,this.y-.5*this.height,this.width,this.height),t.fill(),t.stroke(),this.boundingBox.top=this.top,this.boundingBox.left=this.left,this.boundingBox.right=this.left+this.width,this.boundingBox.bottom=this.top+this.height,this._label(t,this.label,this.x,this.y)},s.prototype._resizeCircle=function(t){if(!this.width){var e=5,i=this.getTextSize(t),s=Math.max(i.width,i.height)+2*e;this.options.radius=s/2,this.width=s,this.height=s,this.options.radius+=.5*Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeRadiusFactor,this.growthIndicator=this.options.radius-.5*s}},s.prototype._drawRawCircle=function(t,e,i,s){var o=2.5,n=this.options.borderWidth,r=this.options.borderWidthSelected||2*this.options.borderWidth;t.strokeStyle=this.selected?this.options.color.highlight.border:this.hover?this.options.color.hover.border:this.options.color.border,this.clusterSize>1&&(t.lineWidth=(this.selected?r:n)+(this.clusterSize>1?o:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.circle(e,i,s+2*t.lineWidth),t.stroke()),t.lineWidth=(this.selected?r:n)+(this.clusterSize>1?o:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.fillStyle=this.selected?this.options.color.highlight.background:this.hover?this.options.color.hover.background:this.options.color.background,t.circle(this.x,this.y,s),t.fill(),t.stroke()},s.prototype._drawCircle=function(t){this._resizeCircle(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,this._drawRawCircle(t,this.x,this.y,this.options.radius),this.boundingBox.top=this.y-this.options.radius,this.boundingBox.left=this.x-this.options.radius,this.boundingBox.right=this.x+this.options.radius,this.boundingBox.bottom=this.y+this.options.radius,this._label(t,this.label,this.x,this.y)},s.prototype._resizeEllipse=function(t){if(!this.width){var e=this.getTextSize(t);this.width=1.5*e.width,this.height=2*e.height,this.width1&&(t.lineWidth=(this.selected?s:i)+(this.clusterSize>1?e:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.ellipse(this.left-2*t.lineWidth,this.top-2*t.lineWidth,this.width+4*t.lineWidth,this.height+4*t.lineWidth),t.stroke()),t.lineWidth=(this.selected?s:i)+(this.clusterSize>1?e:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.fillStyle=this.selected?this.options.color.highlight.background:this.hover?this.options.color.hover.background:this.options.color.background,t.ellipse(this.left,this.top,this.width,this.height),t.fill(),t.stroke(),this.boundingBox.top=this.top,this.boundingBox.left=this.left,this.boundingBox.right=this.left+this.width,this.boundingBox.bottom=this.top+this.height,this._label(t,this.label,this.x,this.y)},s.prototype._drawDot=function(t){this._drawShape(t,"circle")},s.prototype._drawTriangle=function(t){this._drawShape(t,"triangle")},s.prototype._drawTriangleDown=function(t){this._drawShape(t,"triangleDown")},s.prototype._drawSquare=function(t){this._drawShape(t,"square")},s.prototype._drawStar=function(t){this._drawShape(t,"star")},s.prototype._resizeShape=function(){if(!this.width){this.options.radius=this.baseRadiusValue;var t=2*this.options.radius;this.width=t,this.height=t,this.width+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeWidthFactor,this.height+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeHeightFactor,this.options.radius+=.5*Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeRadiusFactor,this.growthIndicator=this.width-t}},s.prototype._drawShape=function(t,e){this._resizeShape(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2;var i=2.5,s=this.options.borderWidth,o=this.options.borderWidthSelected||2*this.options.borderWidth,n=2;switch(e){case"dot":n=2;break;case"square":n=2;break;case"triangle":n=3;break;case"triangleDown":n=3;break;case"star":n=4}t.strokeStyle=this.selected?this.options.color.highlight.border:this.hover?this.options.color.hover.border:this.options.color.border,this.clusterSize>1&&(t.lineWidth=(this.selected?o:s)+(this.clusterSize>1?i:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t[e](this.x,this.y,this.options.radius+n*t.lineWidth),t.stroke()),t.lineWidth=(this.selected?o:s)+(this.clusterSize>1?i:0),t.lineWidth*=this.networkScaleInv,t.lineWidth=Math.min(this.width,t.lineWidth),t.fillStyle=this.selected?this.options.color.highlight.background:this.hover?this.options.color.hover.background:this.options.color.background,t[e](this.x,this.y,this.options.radius),t.fill(),t.stroke(),this.boundingBox.top=this.y-this.options.radius,this.boundingBox.left=this.x-this.options.radius,this.boundingBox.right=this.x+this.options.radius,this.boundingBox.bottom=this.y+this.options.radius,this.label&&(this._label(t,this.label,this.x,this.y+this.height/2,void 0,"hanging",!0),this.boundingBox.left=Math.min(this.boundingBox.left,this.labelDimensions.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelDimensions.left+this.labelDimensions.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelDimensions.height))},s.prototype._resizeText=function(t){if(!this.width){var e=5,i=this.getTextSize(t);this.width=i.width+2*e,this.height=i.height+2*e,this.width+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeWidthFactor,this.height+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeHeightFactor,this.options.radius+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeRadiusFactor,this.growthIndicator=this.width-(i.width+2*e)}},s.prototype._drawText=function(t){this._resizeText(t),this.left=this.x-this.width/2,this.top=this.y-this.height/2,this._label(t,this.label,this.x,this.y),this.boundingBox.top=this.top,this.boundingBox.left=this.left,this.boundingBox.right=this.left+this.width,this.boundingBox.bottom=this.top+this.height},s.prototype._resizeIcon=function(){if(!this.width){var t=5,e={width:Number(this.options.iconSize),height:Number(this.options.iconSize)};this.width=e.width+2*t,this.height=e.height+2*t,this.width+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeWidthFactor,this.height+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeHeightFactor,this.options.radius+=Math.min(this.clusterSize-1,this.maxNodeSizeIncrements)*this.clusterSizeRadiusFactor,this.growthIndicator=this.width-(e.width+2*t)}},s.prototype._drawIcon=function(t){if(this._resizeIcon(t),this.options.iconSize=this.options.iconSize||50,this.left=this.x-this.width/2,this.top=this.y-this.height/2,this._icon(t),this.boundingBox.top=this.y-this.options.iconSize/2,this.boundingBox.left=this.x-this.options.iconSize/2,this.boundingBox.right=this.x+this.options.iconSize/2,this.boundingBox.bottom=this.y+this.options.iconSize/2,this.label){var e=5;this._label(t,this.label,this.x,this.y+this.height/2+e,"top",!0),this.boundingBox.left=Math.min(this.boundingBox.left,this.labelDimensions.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelDimensions.left+this.labelDimensions.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelDimensions.height)}},s.prototype._icon=function(t){var e=Number(this.options.iconSize)*this.networkScale;if(this.options.icon&&e>this.options.fontDrawThreshold-1){var i=Number(this.options.iconSize);t.font=(this.selected?"bold ":"")+i+"px "+this.options.iconFontFace,t.fillStyle=this.options.iconColor||"black",t.textAlign="center",t.textBaseline="middle",t.fillText(this.options.icon,this.x,this.y)}},s.prototype._label=function(t,e,i,s,n,r,a){var h=Number(this.options.fontSize)*this.networkScale;if(e&&h>=this.options.fontDrawThreshold-1){var d=Number(this.options.fontSize);h>=this.options.fontSizeMaxVisible&&(d=Number(this.options.fontSizeMaxVisible)*this.networkScaleInv);var l=this.options.fontColor||"#000000",c=this.options.fontStrokeColor;if(h<=this.options.fontDrawThreshold){var p=Math.max(0,Math.min(1,1-(this.options.fontDrawThreshold-h)));l=o.overrideOpacity(l,p),c=o.overrideOpacity(c,p)}t.font=(this.selected?"bold ":"")+d+"px "+this.options.fontFace;var u=e.split("\n"),m=u.length,f=s+(1-m)/2*d;1==a&&(f=s+(1-m)/(2*d));for(var g=t.measureText(u[0]).width,v=1;m>v;v++){var y=t.measureText(u[v]).width;g=y>g?y:g}var b=d*m,_=i-g/2,x=s-b/2;"hanging"==r&&(x+=.5*d,x+=4,f+=4),this.labelDimensions={top:x,left:_,width:g,height:b,yLine:f},void 0!==this.options.fontFill&&null!==this.options.fontFill&&"none"!==this.options.fontFill&&(t.fillStyle=this.options.fontFill,t.fillRect(_,x,g,b)),t.fillStyle=l,t.textAlign=n||"center",t.textBaseline=r||"middle",this.options.fontStrokeWidth>0&&(t.lineWidth=this.options.fontStrokeWidth,t.strokeStyle=c,t.lineJoin="round");for(var v=0;m>v;v++)this.options.fontStrokeWidth&&t.strokeText(u[v],i,f),t.fillText(u[v],i,f),f+=d}},s.prototype.getTextSize=function(t){if(void 0!==this.label){var e=Number(this.options.fontSize);e*this.networkScale>this.options.fontSizeMaxVisible&&(e=Number(this.options.fontSizeMaxVisible)*this.networkScaleInv),t.font=(this.selected?"bold ":"")+e+"px "+this.options.fontFace;for(var i=this.label.split("\n"),s=(e+4)*i.length,o=0,n=0,r=i.length;r>n;n++)o=Math.max(o,t.measureText(i[n]).width);return{width:o,height:s,lineCount:i.length}}return{width:0,height:0,lineCount: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.y0){var i=this.groupIndex%this.groupsArray.length;this.groupIndex++,e={},e.color=this.groups[this.groupsArray[i]],this.groups[t]=e}else{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,this.groupsArray.push(t),e},t.exports=s},function(t){function e(){this.images={},this.imageBroken={},this.callback=void 0}e.prototype.setOnloadCallback=function(t){this.callback=t},e.prototype.load=function(t,e){var i=this.images[t];if(void 0===i){var s=this;i=new Image,i.onload=function(){0==this.width&&(document.body.appendChild(this),this.width=this.offsetWidth,this.height=this.offsetHeight,document.body.removeChild(this)),s.callback&&(s.images[t]=i,s.callback(this))},i.onerror=function(){void 0===e?(console.error("Could not load image:",t),delete this.src,s.callback&&s.callback(this)):s.imageBroken[t]===!0?this.src==e?(console.error("Could not load brokenImage:",e),delete this.src,s.callback&&s.callback(this)):(console.error("Could not load image:",t),this.src=e):(console.error("Could not load image:",t),this.src=e,s.imageBroken[t]=!0)},i.src=t}return i},t.exports=e},function(t){function e(t,e,i,s,o){this.container=t?t:document.body,void 0===o&&("object"==typeof e?(o=e,e=void 0):"object"==typeof s?(o=s,s=void 0):o={fontColor:"black",fontSize:14,fontFace:"verdana",color:{border:"#666",background:"#FFFFC6"}}),this.x=0,this.y=0,this.padding=5,this.hidden=!1,void 0!==e&&void 0!==i&&this.setPosition(e,i),void 0!==s&&this.setText(s),this.frame=document.createElement("div"),this.frame.className="network-tooltip",this.frame.style.color=o.fontColor,this.frame.style.backgroundColor=o.color.background,this.frame.style.borderColor=o.color.border,this.frame.style.fontSize=o.fontSize+"px",this.frame.style.fontFamily=o.fontFace,this.container.appendChild(this.frame)}e.prototype.setPosition=function(t,e){this.x=parseInt(t),this.y=parseInt(e)},e.prototype.setText=function(t){t instanceof Element?(this.frame.innerHTML="",this.frame.appendChild(t)):this.frame.innerHTML=t},e.prototype.show=function(t){if(void 0===t&&(t=!0),t){var e=this.frame.clientHeight,i=this.frame.clientWidth,s=this.frame.parentNode.clientHeight,o=this.frame.parentNode.clientWidth,n=this.y-e;n+e+this.padding>s&&(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(N=S.NULL,E="";" "==k||" "==k||"\n"==k||"\r"==k;)o();do{var t=!1;if("#"==k){for(var e=T-1;" "==O.charAt(e)||" "==O.charAt(e);)e--;if("\n"==O.charAt(e)||""==O.charAt(e)){for(;""!=k&&"\n"!=k;)o();t=!0}}if("/"==k&&"/"==n()){for(;""!=k&&"\n"!=k;)o();t=!0}if("/"==k&&"*"==n()){for(;""!=k;){if("*"==k&&"/"==n()){o(),o();break}o()}t=!0}for(;" "==k||" "==k||"\n"==k||"\r"==k;)o()}while(t);if(""==k)return void(N=S.DELIMITER);var i=k+n();if(C[i])return N=S.DELIMITER,E=i,o(),void o();if(C[k])return N=S.DELIMITER,E=k,void o();if(r(k)||"-"==k){for(E+=k,o();r(k);)E+=k,o();return"false"==E?E=!1:"true"==E?E=!0:isNaN(Number(E))||(E=Number(E)),void(N=S.IDENTIFIER)}if('"'==k){for(o();""!=k&&('"'!=k||'"'==k&&'"'==n());)E+=k,'"'==k&&o(),o();if('"'!=k)throw x('End of string " expected');return o(),void(N=S.IDENTIFIER)}for(N=S.UNKNOWN;""!=k;)E+=k,o();throw new SyntaxError('Syntax error in part "'+w(E,30)+'"')}function u(){var t={};if(s(),p(),"strict"==E&&(t.strict=!0,p()),("graph"==E||"digraph"==E)&&(t.type=E,p()),N==S.IDENTIFIER&&(t.id=E,p()),"{"!=E)throw x("Angle bracket { expected");if(p(),m(t),"}"!=E)throw x("Angle bracket } expected");if(p(),""!==E)throw x("End of file expected");return p(),delete t.node,delete t.edge,delete t.graph,t +}function m(t){for(;""!==E&&"}"!=E;)f(t),";"==E&&p()}function f(t){var e=g(t);if(e)return void b(t,e);var i=v(t);if(!i){if(N!=S.IDENTIFIER)throw x("Identifier expected");var s=E;if(p(),"="==E){if(p(),N!=S.IDENTIFIER)throw x("Identifier expected");t[s]=E,p()}else y(t,s)}}function g(t){var e=null;if("subgraph"==E&&(e={},e.type="subgraph",p(),N==S.IDENTIFIER&&(e.id=E,p())),"{"==E){if(p(),e||(e={}),e.parent=t,e.node=t.node,e.edge=t.edge,e.graph=t.graph,m(e),"}"!=E)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"==E?(p(),t.node=_(),"node"):"edge"==E?(p(),t.edge=_(),"edge"):"graph"==E?(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(;"->"==E||"--"==E;){var i,s=E;p();var o=g(t);if(o)i=o;else{if(N!=S.IDENTIFIER)throw x("Identifier or subgraph expected");i=E,d(t,{id:i}),p()}var n=_(),r=c(t,e,i,s,n);l(t,r),e=i}}function _(){for(var t=null;"["==E;){for(p(),t={};""!==E&&"]"!=E;){if(N!=S.IDENTIFIER)throw x("Attribute name expected");var e=E;if(p(),"="!=E)throw x("Equal sign = expected");if(p(),N!=S.IDENTIFIER)throw x("Attribute value expected");var i=E;h(t,e,i),p(),","==E&&p()}if("]"!=E)throw x("Bracket ] expected");p()}return t}function x(t){return new SyntaxError(t+', got "'+w(E,30)+'" (char '+T+")")}function w(t,e){return t.length<=e?t:t.substr(0,27)+"..."}function D(t,e,i){Array.isArray(t)?t.forEach(function(t){Array.isArray(e)?e.forEach(function(e){i(t,e)}):i(t,e)}):Array.isArray(e)?e.forEach(function(e){i(t,e)}):i(t,e)}function M(t){var e=i(t),s={nodes:[],edges:[],options:{}};if(e.nodes&&e.nodes.forEach(function(t){var e={id:t.id,label:String(t.label||t.id)};a(e,t.attr),e.image&&(e.shape="image"),s.nodes.push(e)}),e.edges){var o=function(t){var e={from:t.from,to:t.to};return a(e,t.attr),e.style="->"==t.type?"arrow":"line",e};e.edges.forEach(function(t){var e,i;e=t.from instanceof Object?t.from.nodes:{id:t.from},i=t.to instanceof Object?t.to.nodes:{id:t.to},t.from instanceof Object&&t.from.edges&&t.from.edges.forEach(function(t){var e=o(t);s.edges.push(e)}),D(e,i,function(e,i){var n=c(s,e.id,i.id,t.type,t.attr),r=o(n);s.edges.push(r)}),t.to instanceof Object&&t.to.edges&&t.to.edges.forEach(function(t){var e=o(t);s.edges.push(e)})})}return e.attr&&(s.options=e.attr),s}var S={NULL:0,DELIMITER:1,IDENTIFIER:2,UNKNOWN:3},C={"{":!0,"}":!0,"[":!0,"]":!0,";":!0,"=":!0,",":!0,"->":!0,"--":!0},O="",T=0,k="",E="",N=S.NULL,L=/[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;rthis.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 d;d=document.getElementById("graph_BH_gc"),d.onchange=a.bind(this,"graph_BH_gc",-1,"physics_barnesHut_gravitationalConstant"),d=document.getElementById("graph_BH_cg"),d.onchange=a.bind(this,"graph_BH_cg",1,"physics_centralGravity"),d=document.getElementById("graph_BH_sc"),d.onchange=a.bind(this,"graph_BH_sc",1,"physics_springConstant"),d=document.getElementById("graph_BH_sl"),d.onchange=a.bind(this,"graph_BH_sl",1,"physics_springLength"),d=document.getElementById("graph_BH_damp"),d.onchange=a.bind(this,"graph_BH_damp",1,"physics_damping"),d=document.getElementById("graph_R_nd"),d.onchange=a.bind(this,"graph_R_nd",1,"physics_repulsion_nodeDistance"),d=document.getElementById("graph_R_cg"),d.onchange=a.bind(this,"graph_R_cg",1,"physics_centralGravity"),d=document.getElementById("graph_R_sc"),d.onchange=a.bind(this,"graph_R_sc",1,"physics_springConstant"),d=document.getElementById("graph_R_sl"),d.onchange=a.bind(this,"graph_R_sl",1,"physics_springLength"),d=document.getElementById("graph_R_damp"),d.onchange=a.bind(this,"graph_R_damp",1,"physics_damping"),d=document.getElementById("graph_H_nd"),d.onchange=a.bind(this,"graph_H_nd",1,"physics_hierarchicalRepulsion_nodeDistance"),d=document.getElementById("graph_H_cg"),d.onchange=a.bind(this,"graph_H_cg",1,"physics_centralGravity"),d=document.getElementById("graph_H_sc"),d.onchange=a.bind(this,"graph_H_sc",1,"physics_springConstant"),d=document.getElementById("graph_H_sl"),d.onchange=a.bind(this,"graph_H_sl",1,"physics_springLength"),d=document.getElementById("graph_H_damp"),d.onchange=a.bind(this,"graph_H_damp",1,"physics_damping"),d=document.getElementById("graph_H_direction"),d.onchange=a.bind(this,"graph_H_direction",i,"hierarchicalLayout_direction"),d=document.getElementById("graph_H_levsep"),d.onchange=a.bind(this,"graph_H_levsep",1,"hierarchicalLayout_levelSeparation"),d=document.getElementById("graph_H_nspac"),d.onchange=a.bind(this,"graph_H_nspac",1,"hierarchicalLayout_nodeSpacing");var l=document.getElementById("graph_physicsMethod1"),c=document.getElementById("graph_physicsMethod2"),p=document.getElementById("graph_physicsMethod3");c.checked=!0,this.constants.physics.barnesHut.enabled&&(l.checked=!0),this.constants.hierarchicalLayout.enabled&&(p.checked=!0);var u=document.getElementById("graph_toggleSmooth"),m=document.getElementById("graph_repositionNodes"),f=document.getElementById("graph_generateOptions");u.onclick=s.bind(this),m.onclick=o.bind(this),f.onclick=n.bind(this),u.style.background=1==this.constants.smoothCurves&&0==this.constants.dynamicSmoothCurves?"#A4FF56":"#FF8532",r.apply(this),l.onchange=r.bind(this),c.onchange=r.bind(this),p.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){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,f=this.constants.physics.repulsion.nodeDistance,g=f;for(d=0;di&&(r=.5*g>i?1:v*i+m,r*=0==n?1:1+n*this.constants.clustering.forceAmplification,r/=Math.max(i,.01*g),s=t*r,o=e*r,a.fx-=s,a.fy-=o,h.fx+=s,h.fy+=o)}}},function(t,e){e._calculateNodeForces=function(){var t,e,i,s,o,n,r,a,h,d,l=this.calculationNodes,c=this.calculationNodeIndices,p=this.constants.physics.hierarchicalRepulsion.nodeDistance;for(h=0;hi?-Math.pow(u*i,2)+Math.pow(u*p,2):0,0==i?i=.01:n/=i,s=t*n,o=e*n,r.fx-=s,r.fy-=o,a.fx+=s,a.fy+=o}},e._calculateHierarchicalSpringForces=function(){for(var t,e,i,s,o,n,r,a,h,d=this.edges,l=this.calculationNodes,c=this.calculationNodeIndices,p=0;pn;n++)t=e[i[n]],t.options.mass>0&&(this._getForceContribution(o.root.children.NW,t),this._getForceContribution(o.root.children.NE,t),this._getForceContribution(o.root.children.SW,t),this._getForceContribution(o.root.children.SE,t))}},e._getForceContribution=function(t,e){if(t.childrenCount>0){var i,s,o;if(i=t.centerOfMass.x-e.x,s=t.centerOfMass.y-e.y,o=Math.sqrt(i*i+s*s),o*t.calcSize>this.constants.physics.barnesHut.thetaInverted){0==o&&(o=.1*Math.random(),i=o);var n=this.constants.physics.barnesHut.gravitationalConstant*t.mass*e.options.mass/(o*o*o),r=i*n,a=s*n;e.fx+=r,e.fy+=a}else if(4==t.childrenCount)this._getForceContribution(t.children.NW,e),this._getForceContribution(t.children.NE,e),this._getForceContribution(t.children.SW,e),this._getForceContribution(t.children.SE,e);else if(t.children.data.id!=e.id){0==o&&(o=.5*Math.random(),i=o);var n=this.constants.physics.barnesHut.gravitationalConstant*t.mass*e.options.mass/(o*o*o),r=i*n,a=s*n;e.fx+=r,e.fy+=a}}},e._formBarnesHutTree=function(t,e){for(var i,s=e.length,o=Number.MAX_VALUE,n=Number.MAX_VALUE,r=-Number.MAX_VALUE,a=-Number.MAX_VALUE,h=0;s>h;h++){var d=t[e[h]].x,l=t[e[h]].y;t[e[h]].options.mass>0&&(o>d&&(o=d),d>r&&(r=d),n>l&&(n=l),l>a&&(a=l))}var c=Math.abs(r-o)-Math.abs(a-n);c>0?(n-=.5*c,a+=.5*c):(o+=.5*c,r-=.5*c);var p=1e-5,u=Math.max(p,Math.abs(r-o)),m=.5*u,f=.5*(o+r),g=.5*(n+a),v={root:{centerOfMass:{x:0,y:0},mass:0,range:{minX:f-m,maxX:f+m,minY:g-m,maxY:g+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]],i.options.mass>0&&this._placeInTree(v.root,i);this.barnesHutTree=v},e._updateBranchMass=function(t,e){var i=t.mass+e.options.mass,s=1/i;t.centerOfMass.x=t.centerOfMass.x*t.mass+e.x*e.options.mass,t.centerOfMass.x*=s,t.centerOfMass.y=t.centerOfMass.y*t.mass+e.y*e.options.mass,t.centerOfMass.y*=s,t.mass=i;var o=Math.max(Math.max(e.height,e.radius),e.width);t.maxWidth=t.maxWidthe.x?t.children.NW.range.maxY>e.y?this._placeInRegion(t,e,"NW"):this._placeInRegion(t,e,"SW"):t.children.NW.range.maxY>e.y?this._placeInRegion(t,e,"NE"):this._placeInRegion(t,e,"SE")},e._placeInRegion=function(t,e,i){switch(t.children[i].childrenCount){case 0:t.children[i].children.data=e,t.children[i].childrenCount=1,this._updateBranchMass(t.children[i],e);break;case 1:t.children[i].children.data.x==e.x&&t.children[i].children.data.y==e.y?(e.x+=Math.random(),e.y+=Math.random()):(this._splitBranch(t.children[i]),this._placeInTree(t.children[i],e));break;case 4:this._placeInTree(t.children[i],e)}},e._splitBranch=function(t){var e=null;1==t.childrenCount&&(e=t.children.data,t.mass=0,t.centerOfMass.x=0,t.centerOfMass.y=0),t.childrenCount=4,t.children.data=null,this._insertRegion(t,"NW"),this._insertRegion(t,"NE"),this._insertRegion(t,"SW"),this._insertRegion(t,"SE"),null!=e&&this._placeInTree(t,e)},e._insertRegion=function(t,e){var i,s,o,n,r=.5*t.size;switch(e){case"NW":i=t.range.minX,s=t.range.minX+r,o=t.range.minY,n=t.range.minY+r;break;case"NE":i=t.range.minX+r,s=t.range.maxX,o=t.range.minY,n=t.range.minY+r;break;case"SW":i=t.range.minX,s=t.range.minX+r,o=t.range.minY+r,n=t.range.maxY;break;case"SE":i=t.range.minX+r,s=t.range.maxX,o=t.range.minY+r,n=t.range.maxY}t.children[e]={centerOfMass:{x:0,y:0},mass:0,range:{minX:i,maxX:s,minY:o,maxY:n},size:.5*t.size,calcSize:2*t.calcSize,children:{data:null},maxWidth:0,level:t.level+1,childrenCount:0}},e._drawTree=function(t,e){void 0!==this.barnesHutTree&&(t.lineWidth=1,this._drawBranch(this.barnesHutTree.root,t,e))},e._drawBranch=function(t,e,i){void 0===i&&(i="#FF0000"),4==t.childrenCount&&(this._drawBranch(t.children.NW,e),this._drawBranch(t.children.NE,e),this._drawBranch(t.children.SE,e),this._drawBranch(t.children.SW,e)),e.strokeStyle=i,e.beginPath(),e.moveTo(t.range.minX,t.range.minY),e.lineTo(t.range.maxX,t.range.minY),e.stroke(),e.beginPath(),e.moveTo(t.range.maxX,t.range.minY),e.lineTo(t.range.maxX,t.range.maxY),e.stroke(),e.beginPath(),e.moveTo(t.range.maxX,t.range.maxY),e.lineTo(t.range.minX,t.range.maxY),e.stroke(),e.beginPath(),e.moveTo(t.range.minX,t.range.maxY),e.lineTo(t.range.minX,t.range.minY),e.stroke()}},function(t,e){e.startWithClustering=function(){}},function(t,e,i){var s=i(1),o=i(53);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 o({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](o[0],o[1]):this[t](e))}return this._loadLatestSector(),i},e._doInSupportSector=function(t,e){var i=!1;if(void 0===e)this._switchToSupportSector(),i=this[t]();else{this._switchToSupportSector();var s=Array.prototype.splice.call(arguments,1);i=s.length>1?this[t](s[0],s[1]):this[t](e)}return this._loadLatestSector(),i},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;ei;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,!0)}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,!1,!0)}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(53),n=i(52);e._clearManipulatorBar=function(){this._recursiveDOMDelete(this.manipulationDiv),this.manipulationDOM={},this._manipulationReleaseOverload=function(){},delete this.sectors.support.nodes.targetNode,delete this.sectors.support.nodes.targetViaNode,this.controlNodesActive=!1,this.freezeSimulationEnabled=!1},e._restoreOverloadedFunctions=function(){for(var t in this.cachedFunctions)this.cachedFunctions.hasOwnProperty(t)&&(this[t]=this.cachedFunctions[t],delete this.cachedFunctions[t])},e._toggleEditMode=function(){this.editMode=!this.editMode;var t=this.manipulationDiv,e=this.closeDiv,i=this.editModeDiv;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(){this.boundFunction&&this.off("select",this.boundFunction);var t=this.constants.locales[this.constants.locale];if(void 0!==this.edgeBeingEdited&&(this.edgeBeingEdited._disableControlNodes(),this.edgeBeingEdited=void 0,this.selectedControlNode=null,this.controlNodesActive=!1,this._redraw()),this._restoreOverloadedFunctions(),this.freezeSimulationEnabled=!1,this.blockConnectingEdgeSelection=!1,this.forceAppendSelection=!1,this.manipulationDOM={},1==this.editMode){for(;this.manipulationDiv.hasChildNodes();)this.manipulationDiv.removeChild(this.manipulationDiv.firstChild);this.manipulationDOM.addNodeSpan=document.createElement("span"),this.manipulationDOM.addNodeSpan.className="network-manipulationUI add",this.manipulationDOM.addNodeLabelSpan=document.createElement("span"),this.manipulationDOM.addNodeLabelSpan.className="network-manipulationLabel",this.manipulationDOM.addNodeLabelSpan.innerHTML=t.addNode,this.manipulationDOM.addNodeSpan.appendChild(this.manipulationDOM.addNodeLabelSpan),this.manipulationDOM.seperatorLineDiv1=document.createElement("div"),this.manipulationDOM.seperatorLineDiv1.className="network-seperatorLine",this.manipulationDOM.addEdgeSpan=document.createElement("span"),this.manipulationDOM.addEdgeSpan.className="network-manipulationUI connect",this.manipulationDOM.addEdgeLabelSpan=document.createElement("span"),this.manipulationDOM.addEdgeLabelSpan.className="network-manipulationLabel",this.manipulationDOM.addEdgeLabelSpan.innerHTML=t.addEdge,this.manipulationDOM.addEdgeSpan.appendChild(this.manipulationDOM.addEdgeLabelSpan),this.manipulationDiv.appendChild(this.manipulationDOM.addNodeSpan),this.manipulationDiv.appendChild(this.manipulationDOM.seperatorLineDiv1),this.manipulationDiv.appendChild(this.manipulationDOM.addEdgeSpan),1==this._getSelectedNodeCount()&&this.triggerFunctions.edit?(this.manipulationDOM.seperatorLineDiv2=document.createElement("div"),this.manipulationDOM.seperatorLineDiv2.className="network-seperatorLine",this.manipulationDOM.editNodeSpan=document.createElement("span"),this.manipulationDOM.editNodeSpan.className="network-manipulationUI edit",this.manipulationDOM.editNodeLabelSpan=document.createElement("span"),this.manipulationDOM.editNodeLabelSpan.className="network-manipulationLabel",this.manipulationDOM.editNodeLabelSpan.innerHTML=t.editNode,this.manipulationDOM.editNodeSpan.appendChild(this.manipulationDOM.editNodeLabelSpan),this.manipulationDiv.appendChild(this.manipulationDOM.seperatorLineDiv2),this.manipulationDiv.appendChild(this.manipulationDOM.editNodeSpan)):1==this._getSelectedEdgeCount()&&0==this._getSelectedNodeCount()&&(this.manipulationDOM.seperatorLineDiv3=document.createElement("div"),this.manipulationDOM.seperatorLineDiv3.className="network-seperatorLine",this.manipulationDOM.editEdgeSpan=document.createElement("span"),this.manipulationDOM.editEdgeSpan.className="network-manipulationUI edit",this.manipulationDOM.editEdgeLabelSpan=document.createElement("span"),this.manipulationDOM.editEdgeLabelSpan.className="network-manipulationLabel",this.manipulationDOM.editEdgeLabelSpan.innerHTML=t.editEdge,this.manipulationDOM.editEdgeSpan.appendChild(this.manipulationDOM.editEdgeLabelSpan),this.manipulationDiv.appendChild(this.manipulationDOM.seperatorLineDiv3),this.manipulationDiv.appendChild(this.manipulationDOM.editEdgeSpan)),0==this._selectionIsEmpty()&&(this.manipulationDOM.seperatorLineDiv4=document.createElement("div"),this.manipulationDOM.seperatorLineDiv4.className="network-seperatorLine",this.manipulationDOM.deleteSpan=document.createElement("span"),this.manipulationDOM.deleteSpan.className="network-manipulationUI delete",this.manipulationDOM.deleteLabelSpan=document.createElement("span"),this.manipulationDOM.deleteLabelSpan.className="network-manipulationLabel",this.manipulationDOM.deleteLabelSpan.innerHTML=t.del,this.manipulationDOM.deleteSpan.appendChild(this.manipulationDOM.deleteLabelSpan),this.manipulationDiv.appendChild(this.manipulationDOM.seperatorLineDiv4),this.manipulationDiv.appendChild(this.manipulationDOM.deleteSpan)),this.manipulationDOM.addNodeSpan.onclick=this._createAddNodeToolbar.bind(this),this.manipulationDOM.addEdgeSpan.onclick=this._createAddEdgeToolbar.bind(this),1==this._getSelectedNodeCount()&&this.triggerFunctions.edit?this.manipulationDOM.editNodeSpan.onclick=this._editNode.bind(this):1==this._getSelectedEdgeCount()&&0==this._getSelectedNodeCount()&&(this.manipulationDOM.editEdgeSpan.onclick=this._createEditEdgeToolbar.bind(this)),0==this._selectionIsEmpty()&&(this.manipulationDOM.deleteSpan.onclick=this._deleteSelected.bind(this)),this.closeDiv.onclick=this._toggleEditMode.bind(this);var e=this;this.boundFunction=e._createManipulatorBar,this.on("select",this.boundFunction)}else{for(;this.editModeDiv.hasChildNodes();)this.editModeDiv.removeChild(this.editModeDiv.firstChild);this.manipulationDOM.editModeSpan=document.createElement("span"),this.manipulationDOM.editModeSpan.className="network-manipulationUI edit editmode",this.manipulationDOM.editModeLabelSpan=document.createElement("span"),this.manipulationDOM.editModeLabelSpan.className="network-manipulationLabel",this.manipulationDOM.editModeLabelSpan.innerHTML=t.edit,this.manipulationDOM.editModeSpan.appendChild(this.manipulationDOM.editModeLabelSpan),this.editModeDiv.appendChild(this.manipulationDOM.editModeSpan),this.manipulationDOM.editModeSpan.onclick=this._toggleEditMode.bind(this)}},e._createAddNodeToolbar=function(){this._clearManipulatorBar(),this.boundFunction&&this.off("select",this.boundFunction);var t=this.constants.locales[this.constants.locale];this.manipulationDOM={},this.manipulationDOM.backSpan=document.createElement("span"),this.manipulationDOM.backSpan.className="network-manipulationUI back",this.manipulationDOM.backLabelSpan=document.createElement("span"),this.manipulationDOM.backLabelSpan.className="network-manipulationLabel",this.manipulationDOM.backLabelSpan.innerHTML=t.back,this.manipulationDOM.backSpan.appendChild(this.manipulationDOM.backLabelSpan),this.manipulationDOM.seperatorLineDiv1=document.createElement("div"),this.manipulationDOM.seperatorLineDiv1.className="network-seperatorLine",this.manipulationDOM.descriptionSpan=document.createElement("span"),this.manipulationDOM.descriptionSpan.className="network-manipulationUI none",this.manipulationDOM.descriptionLabelSpan=document.createElement("span"),this.manipulationDOM.descriptionLabelSpan.className="network-manipulationLabel",this.manipulationDOM.descriptionLabelSpan.innerHTML=t.addDescription,this.manipulationDOM.descriptionSpan.appendChild(this.manipulationDOM.descriptionLabelSpan),this.manipulationDiv.appendChild(this.manipulationDOM.backSpan),this.manipulationDiv.appendChild(this.manipulationDOM.seperatorLineDiv1),this.manipulationDiv.appendChild(this.manipulationDOM.descriptionSpan),this.manipulationDOM.backSpan.onclick=this._createManipulatorBar.bind(this);var e=this;this.boundFunction=e._addNode,this.on("select",this.boundFunction)},e._createAddEdgeToolbar=function(){this._clearManipulatorBar(),this._unselectAll(!0),this.freezeSimulationEnabled=!0,this.boundFunction&&this.off("select",this.boundFunction);var t=this.constants.locales[this.constants.locale];this._unselectAll(),this.forceAppendSelection=!1,this.blockConnectingEdgeSelection=!0,this.manipulationDOM={},this.manipulationDOM.backSpan=document.createElement("span"),this.manipulationDOM.backSpan.className="network-manipulationUI back",this.manipulationDOM.backLabelSpan=document.createElement("span"),this.manipulationDOM.backLabelSpan.className="network-manipulationLabel",this.manipulationDOM.backLabelSpan.innerHTML=t.back,this.manipulationDOM.backSpan.appendChild(this.manipulationDOM.backLabelSpan),this.manipulationDOM.seperatorLineDiv1=document.createElement("div"),this.manipulationDOM.seperatorLineDiv1.className="network-seperatorLine",this.manipulationDOM.descriptionSpan=document.createElement("span"),this.manipulationDOM.descriptionSpan.className="network-manipulationUI none",this.manipulationDOM.descriptionLabelSpan=document.createElement("span"),this.manipulationDOM.descriptionLabelSpan.className="network-manipulationLabel",this.manipulationDOM.descriptionLabelSpan.innerHTML=t.edgeDescription,this.manipulationDOM.descriptionSpan.appendChild(this.manipulationDOM.descriptionLabelSpan),this.manipulationDiv.appendChild(this.manipulationDOM.backSpan),this.manipulationDiv.appendChild(this.manipulationDOM.seperatorLineDiv1),this.manipulationDiv.appendChild(this.manipulationDOM.descriptionSpan),this.manipulationDOM.backSpan.onclick=this._createManipulatorBar.bind(this);var e=this;this.boundFunction=e._handleConnect,this.on("select",this.boundFunction),this.cachedFunctions._handleTouch=this._handleTouch,this.cachedFunctions._manipulationReleaseOverload=this._manipulationReleaseOverload,this.cachedFunctions._handleDragStart=this._handleDragStart,this.cachedFunctions._handleDragEnd=this._handleDragEnd,this.cachedFunctions._handleOnHold=this._handleOnHold,this._handleTouch=this._handleConnect,this._manipulationReleaseOverload=function(){},this._handleOnHold=function(){},this._handleDragStart=function(){},this._handleDragEnd=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();var t=this.constants.locales[this.constants.locale];this.manipulationDOM={},this.manipulationDOM.backSpan=document.createElement("span"),this.manipulationDOM.backSpan.className="network-manipulationUI back",this.manipulationDOM.backLabelSpan=document.createElement("span"),this.manipulationDOM.backLabelSpan.className="network-manipulationLabel",this.manipulationDOM.backLabelSpan.innerHTML=t.back,this.manipulationDOM.backSpan.appendChild(this.manipulationDOM.backLabelSpan),this.manipulationDOM.seperatorLineDiv1=document.createElement("div"),this.manipulationDOM.seperatorLineDiv1.className="network-seperatorLine",this.manipulationDOM.descriptionSpan=document.createElement("span"),this.manipulationDOM.descriptionSpan.className="network-manipulationUI none",this.manipulationDOM.descriptionLabelSpan=document.createElement("span"),this.manipulationDOM.descriptionLabelSpan.className="network-manipulationLabel",this.manipulationDOM.descriptionLabelSpan.innerHTML=t.editEdgeDescription,this.manipulationDOM.descriptionSpan.appendChild(this.manipulationDOM.descriptionLabelSpan),this.manipulationDiv.appendChild(this.manipulationDOM.backSpan),this.manipulationDiv.appendChild(this.manipulationDOM.seperatorLineDiv1),this.manipulationDiv.appendChild(this.manipulationDOM.descriptionSpan),this.manipulationDOM.backSpan.onclick=this._createManipulatorBar.bind(this),this.cachedFunctions._handleTouch=this._handleTouch,this.cachedFunctions._manipulationReleaseOverload=this._manipulationReleaseOverload,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._manipulationReleaseOverload=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.freezeSimulationEnabled=!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.edgeBeingEdited._restoreControlNodes(),this._editEdge(e.id,this.edgeBeingEdited.to.id),this.edgeBeingEdited.controlNodes.from.unselect()),1==this.edgeBeingEdited.controlNodes.to.selected&&(this.edgeBeingEdited._restoreControlNodes(),this._editEdge(this.edgeBeingEdited.from.id,e.id),this.edgeBeingEdited.controlNodes.to.unselect())):this.edgeBeingEdited._restoreControlNodes(),this.freezeSimulationEnabled=!1,this._redraw()},e._handleConnect=function(t){if(0==this._getSelectedNodeCount()){var e=this._getNodeAt(t);if(null!=e)if(e.clusterSize>1)alert(this.constants.locales[this.constants.locale].createEdgeError);else{this._selectObject(e,!1);var i=this.sectors.support.nodes;i.targetNode=new o({id:"targetNode"},{},{},this.constants);var s=i.targetNode;s.x=e.x,s.y=e.y,this.edges.connectionEdge=new n({id:"connectionEdge",from:e.id,to:s.id},this,this.constants);var r=this.edges.connectionEdge;r.from=e,r.connected=!0,r.options.smoothCurves={enabled:!0,dynamic:!1,type:"continuous",roundness:.5},r.selected=!0,r.to=s,this.cachedFunctions._handleOnDrag=this._handleOnDrag,this._handleOnDrag=function(t){var e=this._getPointer(t.gesture.center),i=this.edges.connectionEdge;i.to.x=this._XconvertDOMtoCanvas(e.x),i.to.y=this._YconvertDOMtoCanvas(e.y)},this.moving=!0,this.start()}}},e._finishConnect=function(t){if(1==this._getSelectedNodeCount()){var e=this._getPointer(t.gesture.center);this._handleOnDrag=this.cachedFunctions._handleOnDrag,delete this.cachedFunctions._handleOnDrag;var i=this.edges.connectionEdge.fromId;delete this.edges.connectionEdge,delete this.sectors.support.nodes.targetNode,delete this.sectors.support.nodes.targetViaNode;var s=this._getNodeAt(e);null!=s&&(s.clusterSize>1?alert(this.constants.locales[this.constants.locale].createEdgeError):(this._createEdge(i,s.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)throw new Error("The function for add does not support two arguments (data,callback)");var i=this;this.triggerFunctions.add(e,function(t){i.nodesData.add(t),i._createManipulatorBar(),i.moving=!0,i.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)throw new Error("The function for connect does not support two arguments (data,callback)");var s=this;this.triggerFunctions.connect(i,function(t){s.edgesData.add(t),s.moving=!0,s.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)throw new Error("The function for edit does not support two arguments (data, callback)");var s=this;this.triggerFunctions.editEdge(i,function(t){s.edgesData.update(t),s.moving=!0,s.start()})}else this.edgesData.update(i),this.moving=!0,this.start()}},e._editNode=function(){if(!this.triggerFunctions.edit||1!=this.editMode)throw new Error("No edit function has been bound to this button");var t=this._getSelectedNode(),e={id:t.id,label:t.label,group:t.options.group,shape:t.options.shape,color:{background:t.options.color.background,border:t.options.color.border,highlight:{background:t.options.color.highlight.background,border:t.options.color.highlight.border}}};if(2!=this.triggerFunctions.edit.length)throw new Error("The function for edit does not support two arguments (data, callback)"); +var i=this;this.triggerFunctions.edit(e,function(t){i.nodesData.update(t),i._createManipulatorBar(),i.moving=!0,i.start()})},e._deleteSelected=function(){if(!this._selectionIsEmpty()&&1==this.editMode)if(this._clusterInSelection())alert(this.constants.locales[this.constants.locale].deleteClusterError);else{var t=this.getSelectedNodes(),e=this.getSelectedEdges();if(this.triggerFunctions.del){var i=this,s={nodes:t,edges:e};if(2!=this.triggerFunctions.del.length)throw new Error("The function for delete does not support two arguments (data, callback)");this.triggerFunctions.del(s,function(t){i.edgesData.remove(t.edges),i.nodesData.remove(t.nodes),i._unselectAll(),i.moving=!0,i.start()})}else this.edgesData.remove(e),this.nodesData.remove(t),this._unselectAll(),this.moving=!0,this.start()}}},function(t,e,i){var s=(i(1),i(19));e._cleanNavigation=function(){if(0!=this.navigationHammers.existing.length){for(var t=0;t0){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,o.edges.length>1&&this._setLevel(t+1,o.edges,o.id))}},e._setLevelDirected=function(t,e,i){this.nodes[i].hierarchyEnumerated=!0;for(var s,o,n=0;n1&&s.hierarchyEnumerated===!1&&this._setLevelDirected(s.level,s.edges,s.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){e.en={edit:"Edit",del:"Delete selected",back:"Back",addNode:"Add Node",addEdge:"Add Edge",editNode:"Edit Node",editEdge:"Edit Edge",addDescription:"Click in an empty space to place a new node.",edgeDescription:"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.",createEdgeError:"Cannot link edges to a cluster.",deleteClusterError:"Clusters cannot be deleted."},e.en_EN=e.en,e.en_US=e.en,e.nl={edit:"Wijzigen",del:"Selectie verwijderen",back:"Terug",addNode:"Node toevoegen",addEdge:"Link toevoegen",editNode:"Node wijzigen",editEdge:"Link wijzigen",addDescription:"Klik op een leeg gebied om een nieuwe node te maken.",edgeDescription:"Klik op een node en sleep de link naar een andere node om ze te verbinden.",editEdgeDescription:"Klik op de verbindingspunten en sleep ze naar een node om daarmee te verbinden.",createEdgeError:"Kan geen link maken naar een cluster.",deleteClusterError:"Clusters kunnen niet worden verwijderd."},e.nl_NL=e.nl,e.nl_BE=e.nl},function(){"undefined"!=typeof CanvasRenderingContext2D&&(CanvasRenderingContext2D.prototype.circle=function(t,e,i){this.beginPath(),this.arc(t,e,i,0,2*Math.PI,!1)},CanvasRenderingContext2D.prototype.square=function(t,e,i){this.beginPath(),this.rect(t-i,e-i,2*i,2*i)},CanvasRenderingContext2D.prototype.triangle=function(t,e,i){this.beginPath();var s=2*i,o=s/2,n=Math.sqrt(3)/6*s,r=Math.sqrt(s*s-o*o);this.moveTo(t,e-(r-n)),this.lineTo(t+o,e+n),this.lineTo(t-o,e+n),this.lineTo(t,e-(r-n)),this.closePath()},CanvasRenderingContext2D.prototype.triangleDown=function(t,e,i){this.beginPath();var s=2*i,o=s/2,n=Math.sqrt(3)/6*s,r=Math.sqrt(s*s-o*o);this.moveTo(t,e+(r-n)),this.lineTo(t+o,e-n),this.lineTo(t-o,e-n),this.lineTo(t,e+(r-n)),this.closePath()},CanvasRenderingContext2D.prototype.star=function(t,e,i){this.beginPath();for(var s=0;10>s;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),f=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,f,p,f),this.bezierCurveTo(p-h,f,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}})}])}); //# sourceMappingURL=vis.map diff --git a/examples/graph2d/19_labels.html b/examples/graph2d/19_labels.html index a235a57a..7f140180 100644 --- a/examples/graph2d/19_labels.html +++ b/examples/graph2d/19_labels.html @@ -57,6 +57,7 @@ var options = { start: '2014-06-10', end: '2014-06-18', + style:'bar' }; var graph2d = new vis.Graph2d(container, dataset, options); diff --git a/examples/network/39_newClustering.html b/examples/network/39_newClustering.html new file mode 100644 index 00000000..8c403fc1 --- /dev/null +++ b/examples/network/39_newClustering.html @@ -0,0 +1,102 @@ + + + + Network | Basic usage + + + + + + + + + +
+ + + + + diff --git a/lib/network/Edge.js b/lib/network/Edge.js index ccb091c1..adb87b18 100644 --- a/lib/network/Edge.js +++ b/lib/network/Edge.js @@ -23,6 +23,7 @@ function Edge (properties, network, networkConstants) { var fields = ['edges','physics']; var constants = util.selectiveBridgeObject(fields,networkConstants); this.options = constants.edges; + this.physics = constants.physics; this.options['smoothCurves'] = networkConstants['smoothCurves']; @@ -46,13 +47,13 @@ function Edge (properties, network, networkConstants) { this.to = null; // a node this.via = null; // a temp node - this.fromBackup = null; // used to clean up after reconnect - this.toBackup = null;; // used to clean up after reconnect + this.fromBackup = null; // used to clean up after reconnect (used for manipulation) + this.toBackup = null; // used to clean up after reconnect (used for manipulation) // 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 = []; + this.fromArray = []; + this.toArray = []; this.connected = false; @@ -76,10 +77,11 @@ Edge.prototype.setProperties = function(properties) { if (!properties) { return; } + this.properties = properties; var fields = ['style','fontSize','fontFace','fontColor','fontFill','fontStrokeWidth','fontStrokeColor','width', 'widthSelectionMultiplier','hoverWidth','arrowScaleFactor','dash','inheritColor','labelAlignment', 'opacity', - 'customScalingFunction','useGradients' + 'customScalingFunction','useGradients','value' ]; util.selectiveDeepExtend(fields, this.options, properties); @@ -135,9 +137,9 @@ Edge.prototype.connect = function () { this.from = this.network.nodes[this.fromId] || null; this.to = this.network.nodes[this.toId] || null; - this.connected = (this.from && this.to); + this.connected = (this.from !== null && this.to !== null); - if (this.connected) { + if (this.connected === true) { this.from.attachEdge(this); this.to.attachEdge(this); } @@ -259,6 +261,7 @@ Edge.prototype._getColor = function(ctx) { } if (this.colorDirty === true) { + if (this.options.inheritColor == "to") { colorObj = { highlight: this.to.options.color.highlight.border, diff --git a/lib/network/Network.js b/lib/network/Network.js index 203369c7..455c1f3d 100644 --- a/lib/network/Network.js +++ b/lib/network/Network.js @@ -85,6 +85,7 @@ function Network (container, data, options) { fontSizeMin: 14, fontSizeMax: 30, fontSizeMaxVisible: 30, + value: 1, level: -1, color: { border: '#2B7CE9', @@ -109,6 +110,7 @@ function Network (container, data, options) { width: 1, widthSelectionMultiplier: 2, hoverWidth: 1.5, + value:1, style: 'line', color: { color:'#848484', @@ -164,26 +166,33 @@ function Network (container, data, options) { 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, // used for normalization of the cluster levels - clusterByZoom: true // enable clustering through zooming in and out + 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, // used for normalization of the cluster levels + //clusterByZoom: true // enable clustering through zooming in and out }, navigation: { enabled: false @@ -583,11 +592,7 @@ Network.prototype.zoomExtent = function(options, initialZoom, disableStart) { */ Network.prototype._updateNodeIndexList = function() { this._clearNodeIndexList(); - for (var idx in this.nodes) { - if (this.nodes.hasOwnProperty(idx)) { - this.nodeIndices.push(idx); - } - } + this.nodeIndices = Object.keys(this.nodes); }; @@ -1288,7 +1293,6 @@ Network.prototype._zoom = function(scale, pointer) { this._setScale(scale); this._setTranslation(tx, ty); - this.updateClustersDefault(); if (preScaleDragPointer != null) { var postScaleDragPointer = this.canvasToDOM(preScaleDragPointer); @@ -1483,7 +1487,7 @@ Network.prototype._checkShowPopup = function (pointer) { for (id in edges) { if (edges.hasOwnProperty(id)) { var edge = edges[id]; - if (edge.connected && (edge.getTitle() !== undefined) && + if (edge.connected === true && (edge.getTitle() !== undefined) && edge.isOverlappingWith(obj)) { overlappingEdges.push(id); } @@ -1678,7 +1682,6 @@ Network.prototype._addNodes = function(ids) { this._updateCalculationNodes(); this._reconnectEdges(); this._updateValueRange(this.nodes); - this.updateLabels(); }; /** @@ -1914,7 +1917,6 @@ Network.prototype._reconnectEdges = function() { for (id in nodes) { if (nodes.hasOwnProperty(id)) { nodes[id].edges = []; - nodes[id].dynamicEdges = []; } } @@ -2035,7 +2037,7 @@ Network.prototype._redraw = function(hidden, requested) { } } -// this._doInSupportSector("_drawNodes",ctx,true); + //this._doInSupportSector("_drawNodes",ctx,true); // this._drawTree(ctx,"#F00F0F"); // restore original scaling and translation @@ -2215,7 +2217,7 @@ Network.prototype._drawEdges = function(ctx) { if (edges.hasOwnProperty(id)) { var edge = edges[id]; edge.setScale(this.scale); - if (edge.connected) { + if (edge.connected === true) { edges[id].draw(ctx); } } @@ -2442,6 +2444,7 @@ Network.prototype._animationStep = function() { // check if the physics have settled if (this.moving == true) { var startTime = Date.now(); + this._physicsTick(); var physicsTime = Date.now() - startTime; @@ -2595,11 +2598,14 @@ Network.prototype._configureSmoothCurves = function(disableStart) { * * @private */ -Network.prototype._createBezierNodes = function() { +Network.prototype._createBezierNodes = function(specificEdges) { + if (specificEdges === undefined) { + specificEdges = this.edges; + } 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]; + for (var edgeId in specificEdges) { + if (specificEdges.hasOwnProperty(edgeId)) { + var edge = specificEdges[edgeId]; if (edge.via == null) { var nodeId = "edgeId:".concat(edge.id); this.sectors['support']['nodes'][nodeId] = new Node( diff --git a/lib/network/Node.js b/lib/network/Node.js index b88ba8e1..6dd229a4 100644 --- a/lib/network/Node.js +++ b/lib/network/Node.js @@ -33,8 +33,6 @@ function Node(properties, imagelist, grouplist, networkConstants) { this.hover = false; this.edges = []; // all edges connected to this node - this.dynamicEdges = []; - this.reroutedEdges = {}; // set defaults for the properties this.id = undefined; @@ -72,15 +70,6 @@ function Node(properties, imagelist, grouplist, networkConstants) { this.setProperties(properties, constants); - // creating the variables for clustering - this.resetCluster(); - this.clusterSession = 0; - this.clusterSizeWidthFactor = networkConstants.clustering.nodeScaling.width; - this.clusterSizeHeightFactor = networkConstants.clustering.nodeScaling.height; - this.clusterSizeRadiusFactor = networkConstants.clustering.nodeScaling.radius; - this.maxNodeSizeIncrements = networkConstants.clustering.maxNodeSizeIncrements; - this.growthIndicator = 0; - // variables to tell the node about the network. this.networkScaleInv = 1; this.networkScale = 1; @@ -101,18 +90,6 @@ Node.prototype.revertPosition = function() { } -/** - * (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 = []; -}; - /** * Attach a edge to the node * @param {Edge} edge @@ -121,9 +98,6 @@ 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); - } }; /** @@ -135,10 +109,6 @@ Node.prototype.detachEdge = function(edge) { if (index != -1) { this.edges.splice(index, 1); } - index = this.dynamicEdges.indexOf(edge); - if (index != -1) { - this.dynamicEdges.splice(index, 1); - } }; @@ -151,10 +121,12 @@ Node.prototype.setProperties = function(properties, constants) { if (!properties) { return; } + this.properties = properties; - var fields = ['borderWidth','borderWidthSelected','shape','image','brokenImage','radius','fontColor', - 'fontSize','fontFace','fontFill','fontStrokeWidth','fontStrokeColor','group','mass','fontDrawThreshold', - 'scaleFontWithValue','fontSizeMaxVisible','customScalingFunction','iconFontFace', 'icon', 'iconColor', 'iconSize' + var fields = ['borderWidth', 'borderWidthSelected', 'shape', 'image', 'brokenImage', 'radius', 'fontColor', + 'fontSize', 'fontFace', 'fontFill', 'fontStrokeWidth', 'fontStrokeColor', 'group', 'mass', 'fontDrawThreshold', + 'scaleFontWithValue', 'fontSizeMaxVisible', 'customScalingFunction', 'iconFontFace', 'icon', 'iconColor', 'iconSize', + 'value' ]; util.selectiveDeepExtend(fields, this.options, properties); @@ -424,6 +396,7 @@ Node.prototype.discreteStepLimited = function(interval, maxVelocity) { this.fy = 0; this.vy = 0; } + }; /** @@ -547,29 +520,11 @@ Node.prototype._resizeImage = function (ctx) { } this.width = width; this.height = height; - - this.growthIndicator = 0; - if (this.width > 0 && this.height > 0) { - this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeWidthFactor; - this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeHeightFactor; - this.options.radius+= Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeRadiusFactor; - this.growthIndicator = this.width - width; - } } }; Node.prototype._drawImageAtPosition = function (ctx) { 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); - } - // draw the image ctx.globalAlpha = 1.0; ctx.drawImage(this.imageObj, this.left, this.top, this.width, this.height); @@ -619,12 +574,6 @@ Node.prototype._resizeCircularImage = function (ctx) { var diameter = this.options.radius * 2; 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.options.radius += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeRadiusFactor; - this.growthIndicator = this.options.radius- 0.5*diameter; this._swapToImageResizeWhenImageLoaded = true; } } @@ -678,12 +627,6 @@ Node.prototype._resizeBox = function (ctx) { var textSize = this.getTextSize(ctx); this.width = textSize.width + 2 * margin; this.height = textSize.height + 2 * margin; - - this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeWidthFactor; - this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeHeightFactor; - this.growthIndicator = this.width - (textSize.width + 2 * margin); -// this.options.radius+= Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeRadiusFactor; - } }; @@ -693,22 +636,11 @@ Node.prototype._drawBox = function (ctx) { this.left = this.x - this.width / 2; this.top = this.y - this.height / 2; - var clusterLineWidth = 2.5; var borderWidth = this.options.borderWidth; var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; ctx.strokeStyle = this.selected ? this.options.color.highlight.border : this.hover ? this.options.color.hover.border : this.options.color.border; - - // draw the outer border - if (this.clusterSize > 1) { - ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); - ctx.lineWidth *= this.networkScaleInv; - ctx.lineWidth = Math.min(this.width,ctx.lineWidth); - - ctx.roundRect(this.left-2*ctx.lineWidth, this.top-2*ctx.lineWidth, this.width+4*ctx.lineWidth, this.height+4*ctx.lineWidth, this.options.radius); - ctx.stroke(); - } - ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); + ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth); ctx.lineWidth *= this.networkScaleInv; ctx.lineWidth = Math.min(this.width,ctx.lineWidth); @@ -734,12 +666,6 @@ Node.prototype._resizeDatabase = function (ctx) { var size = textSize.width + 2 * margin; this.width = size; this.height = size; - - // scaling used for clustering - this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeWidthFactor; - this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeHeightFactor; - this.options.radius+= Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeRadiusFactor; - this.growthIndicator = this.width - size; } }; @@ -748,22 +674,11 @@ Node.prototype._drawDatabase = function (ctx) { this.left = this.x - this.width / 2; this.top = this.y - this.height / 2; - var clusterLineWidth = 2.5; var borderWidth = this.options.borderWidth; var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; ctx.strokeStyle = this.selected ? this.options.color.highlight.border : this.hover ? this.options.color.hover.border : this.options.color.border; - - // draw the outer border - if (this.clusterSize > 1) { - ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); - ctx.lineWidth *= this.networkScaleInv; - ctx.lineWidth = Math.min(this.width,ctx.lineWidth); - - 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.selected ? selectionLineWidth : borderWidth); ctx.lineWidth *= this.networkScaleInv; ctx.lineWidth = Math.min(this.width,ctx.lineWidth); @@ -790,32 +705,16 @@ Node.prototype._resizeCircle = function (ctx) { 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.options.radius += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeRadiusFactor; - this.growthIndicator = this.options.radius- 0.5*diameter; } }; Node.prototype._drawRawCircle = function (ctx, x, y, radius) { - var clusterLineWidth = 2.5; var borderWidth = this.options.borderWidth; var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; ctx.strokeStyle = this.selected ? this.options.color.highlight.border : this.hover ? this.options.color.hover.border : this.options.color.border; - // draw the outer border - if (this.clusterSize > 1) { - ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); - ctx.lineWidth *= this.networkScaleInv; - ctx.lineWidth = Math.min(this.width,ctx.lineWidth); - - ctx.circle(x, y, radius+2*ctx.lineWidth); - ctx.stroke(); - } - ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); + ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth); ctx.lineWidth *= this.networkScaleInv; ctx.lineWidth = Math.min(this.width,ctx.lineWidth); @@ -850,12 +749,6 @@ Node.prototype._resizeEllipse = function (ctx) { this.width = this.height; } 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.options.radius += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeRadiusFactor; - this.growthIndicator = this.width - defaultSize; } }; @@ -864,22 +757,12 @@ Node.prototype._drawEllipse = function (ctx) { this.left = this.x - this.width / 2; this.top = this.y - this.height / 2; - var clusterLineWidth = 2.5; var borderWidth = this.options.borderWidth; var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; ctx.strokeStyle = this.selected ? this.options.color.highlight.border : this.hover ? this.options.color.hover.border : this.options.color.border; - // draw the outer border - if (this.clusterSize > 1) { - ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); - ctx.lineWidth *= this.networkScaleInv; - ctx.lineWidth = Math.min(this.width,ctx.lineWidth); - - 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.selected ? selectionLineWidth : borderWidth); ctx.lineWidth *= this.networkScaleInv; ctx.lineWidth = Math.min(this.width,ctx.lineWidth); @@ -923,12 +806,6 @@ Node.prototype._resizeShape = function (ctx) { var size = 2 * this.options.radius; this.width = size; this.height = size; - - // scaling used for clustering - this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeWidthFactor; - this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeHeightFactor; - this.options.radius+= Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeRadiusFactor; - this.growthIndicator = this.width - size; } }; @@ -938,7 +815,6 @@ Node.prototype._drawShape = function (ctx, shape) { this.left = this.x - this.width / 2; this.top = this.y - this.height / 2; - var clusterLineWidth = 2.5; var borderWidth = this.options.borderWidth; var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; var radiusMultiplier = 2; @@ -953,16 +829,7 @@ Node.prototype._drawShape = function (ctx, shape) { } ctx.strokeStyle = this.selected ? this.options.color.highlight.border : this.hover ? this.options.color.hover.border : this.options.color.border; - // draw the outer border - if (this.clusterSize > 1) { - ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); - ctx.lineWidth *= this.networkScaleInv; - ctx.lineWidth = Math.min(this.width,ctx.lineWidth); - - ctx[shape](this.x, this.y, this.options.radius+ radiusMultiplier * ctx.lineWidth); - ctx.stroke(); - } - ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth) + ((this.clusterSize > 1) ? clusterLineWidth : 0.0); + ctx.lineWidth = (this.selected ? selectionLineWidth : borderWidth); ctx.lineWidth *= this.networkScaleInv; ctx.lineWidth = Math.min(this.width,ctx.lineWidth); @@ -990,12 +857,6 @@ Node.prototype._resizeText = function (ctx) { 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.options.radius+= Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeRadiusFactor; - this.growthIndicator = this.width - (textSize.width + 2 * margin); } }; @@ -1022,12 +883,6 @@ Node.prototype._resizeIcon = function (ctx) { }; this.width = iconSize.width + 2 * margin; this.height = iconSize.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.options.radius += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * this.clusterSizeRadiusFactor; - this.growthIndicator = this.width - (iconSize.width + 2 * margin); } }; diff --git a/lib/network/mixins/ClusterMixin.js b/lib/network/mixins/ClusterMixin.js index f3a33587..81188960 100644 --- a/lib/network/mixins/ClusterMixin.js +++ b/lib/network/mixins/ClusterMixin.js @@ -1,1050 +1,526 @@ -/** - * Creation of the ClusterMixin var. - * - * This contains all the functions the Network object can use to employ clustering - */ +var Node = require('../Node'); +var Edge = require('../Edge'); +var util = require('../../util'); -/** -* This is only called in the constructor of the network object -* -*/ exports.startWithClustering = function() { - // cluster if the data set is big - this.clusterToFit(this.constants.clustering.initialMaxNodes, true); - - // updates the lables after clustering - this.updateLabels(); - - // this is called here because if clusterin is disabled, the start and stabilize are called in - // the setData function. - if (this.constants.stabilize == true) { - this._stabilize(); - } - this.start(); -}; - -/** - * 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 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.0) { - this.forceAggregateHubs(true); - this.normalizeClusterLevels(); - } - else { - this.increaseClusterLevel(); // this also includes a cluster normalization - } - this.forceAggregateHubs(true); - numberOfNodes = this.nodeIndices.length; - level += 1; - } + this.clusteredNodes = {}; + this.moving = true; + this.start(); +} - // 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 will unpack the cluster back one level. * - * @param node | Node object: cluster to open. + * @param hubsize + * @param options */ -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); - - // update the index list and labels - this._updateNodeIndexList(); - this._updateCalculationNodes(); - this.updateLabels(); +exports.clusterByConnectionCount = function(hubsize, options) { + if (hubsize === undefined) { + hubsize = this._getHubSize(); } - - // if the simulation was settled, we restart the simulation if a cluster has been formed or expanded - if (this.moving != isMovingBeforeClustering) { - this.start(); + else if (tyepof(hubsize) == "object") { + options = this._checkOptions(hubsize); + hubsize = this._getHubSize(); } -}; - - -/** - * This calls the updateClustes with default arguments - */ -exports.updateClustersDefault = function() { - if (this.constants.clustering.enabled == true && this.constants.clustering.clusterByZoom == true) { - this.updateClusters(0,false,false); - } -}; - -/** - * 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); -}; - - -/** - * 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 - * - */ -exports.updateClusters = function(zoomDirection,recursive,force,doNotStart) { - var isMovingBeforeClustering = this.moving; - var amountOfNodes = this.nodeIndices.length; - - var detectedZoomingIn = (this.previousScale < this.scale && zoomDirection == 0); - var detectedZoomingOut = (this.previousScale > this.scale && zoomDirection == 0); - - // on zoom out collapse the sector if the scale is at the level the sector was made - if (detectedZoomingOut == true) { - this._collapseSector(); - } - - // check if we zoom in or out - if (detectedZoomingOut == true || 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 (detectedZoomingIn == true || zoomDirection == 1) { // zoom in - if (force == true) { - // _openClusters checks for each node if the formationScale of the cluster is smaller than - // the current scale and if so, declusters. When forced, all clusters are reduced by one step - this._openClusters(recursive,force); - } - else { - // if a cluster takes up a set percentage of the active window - //this._openClustersBySize(); - this._openClusters(recursive, false); + var nodesToCluster = []; + for (var i = 0; i < this.nodeIndices.length; i++) { + var node = this.nodes[this.nodeIndices[i]]; + if (node.edges.length >= hubsize) { + nodesToCluster.push(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 && (detectedZoomingOut == true || zoomDirection == -1)) { - this._aggregateHubs(force); - this._updateNodeIndexList(); + for (var i = 0; i < nodesToCluster.length; i++) { + var node = this.nodes[nodesToCluster[i]]; + this.clusterByConnection(node,options,{},{},true); } + this._wrapUp(); +} - // we now reduce chains. - if (detectedZoomingOut == true || zoomDirection == -1) { // zoom out - this.handleChains(); - this._updateNodeIndexList(); +exports.clusterByNodeData = function(options, doNotUpdateCalculationNodes) { + if (options === undefined) { + throw new Error("Cannot call clusterByNodeData without options.") } - - this.previousScale = this.scale; - - // update labels - 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(); + if (options.joinCondition === undefined) { + throw new Error("Cannot call clusterByNodeData without a joinCondition function in the options."); } - if (doNotStart == false || doNotStart === undefined) { - // if the simulation was settled, we restart the simulation if a cluster has been formed or expanded - if (this.moving != isMovingBeforeClustering) { - this.start(); - } - } - - this._updateCalculationNodes(); -}; - -/** - * This function handles the chains. It is called on every updateClusters(). - */ -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) - - } -}; - -/** - * this functions starts clustering by hubs - * The minimum hub threshold is set globally - * - * @private - */ -exports._aggregateHubs = function(force) { - this._getHubSize(); - this._formClustersByHub(force,false); -}; - - -/** - * This function forces hubs to form. - * - */ -exports.forceAggregateHubs = function(doNotStart) { - var isMovingBeforeClustering = this.moving; - var amountOfNodes = this.nodeIndices.length; - - this._aggregateHubs(true); - - // update the index list, dynamic edges and labels - this._updateNodeIndexList(); - this.updateLabels(); - - this._updateCalculationNodes(); + // check if the options object is fine, append if needed + options = this._checkOptions(options); - // if a cluster was formed, we increase the clusterSession - if (this.nodeIndices.length != amountOfNodes) { - this.clusterSession += 1; - } + var childNodesObj = {}; + var childEdgesObj = {} - 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(); + // collect the nodes that will be in the cluster + for (var i = 0; i < this.nodeIndices.length; i++) { + var nodeId = this.nodeIndices[i]; + var clonedOptions = this._cloneOptions(nodeId); + if (options.joinCondition(clonedOptions) == true) { + childNodesObj[nodeId] = this.nodes[nodeId]; } } -}; -/** - * If a cluster takes up more than a set percentage of the screen, open the cluster - * - * @private - */ -exports._openClustersBySize = function() { - if (this.constants.clustering.clusterByZoom == true) { - 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); - } - } - } - } - } -}; + this._cluster(childNodesObj, childEdgesObj, options, doNotUpdateCalculationNodes); +} +exports.clusterOutliers = function(options, doNotUpdateCalculationNodes) { + options = this._checkOptions(options); -/** - * 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._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(); - } -}; + var clusters = [] -/** - * 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) { - if (openAll === undefined) { - openAll = false; - } - // this means that on a double tap event or a zoom event, the cluster fully unpacks if it is smaller than 20 - - recursive = openAll || 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]; - - // 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); - } + // collect the nodes that will be in the cluster + for (var i = 0; i < this.nodeIndices.length; i++) { + var childNodesObj = {}; + var childEdgesObj = {}; + var nodeId = this.nodeIndices[i]; + if (this.nodes[nodeId].edges.length == 1) { + var edge = this.nodes[nodeId].edges[0]; + var childNodeId = this._getConnectedId(edge, nodeId); + if (childNodeId != nodeId) { + if (options.joinCondition === undefined) { + childNodesObj[nodeId] = this.nodes[nodeId]; + childNodesObj[childNodeId] = this.nodes[childNodeId]; + } + else { + var clonedOptions = this._cloneOptions(nodeId); + if (options.joinCondition(clonedOptions) == true) { + childNodesObj[nodeId] = this.nodes[nodeId]; } - else { - if (this._nodeInActiveArea(parentNode)) { - this._expelChildFromParent(parentNode,containedNodeId,recursive,force,openAll); - } + clonedOptions = this._cloneOptions(childNodeId); + if (options.joinCondition(clonedOptions) == true) { + childNodesObj[childNodeId] = this.nodes[childNodeId]; } } + clusters.push({nodes:childNodesObj, edges:childEdgesObj}) } } } -}; - -/** - * 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._expelChildFromParent = function(parentNode, containedNodeId, recursive, force, openAll) { - var childNode = parentNode.containedNodes[containedNodeId] - - // if child node has been added on smaller scale than current, kick out - if (childNode.formationScale < this.scale || force == true) { - // unselect all selected items - this._unselectAll(); - - // put the child node back in the global nodes object - this.nodes[containedNodeId] = childNode; - - // release the contained edges from this childNode back into the global edges - this._releaseContainedEdges(parentNode,childNode); - - // reconnect rerouted edges to the childNode - this._connectEdgeBackToChild(parentNode,childNode); - - // validate all edges in dynamicEdges - this._validateEdges(parentNode); - - // undo the changes from the clustering operation on the parent node - parentNode.options.mass -= childNode.options.mass; - parentNode.clusterSize -= childNode.clusterSize; - parentNode.options.fontSize = Math.min(this.constants.clustering.maxFontSize, this.constants.nodes.fontSize + this.constants.clustering.fontSizeMultiplier*(parentNode.clusterSize-1)); - - // 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; - - // 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; + for (var i = 0; i < clusters.length; i++) { + this._cluster(clusters[i].nodes, clusters[i].edges, options, true) } - // check if a further expansion step is possible if recursivity is enabled - if (recursive == true) { - this._expandClusterNode(childNode,recursive,force,openAll); - } -}; + this._wrapUp(); + +} /** - * position the bezier nodes at the center of the edges * - * @param node - * @private + * @param nodeId + * @param options + * @param doNotUpdateCalculationNodes */ -exports._repositionBezierNodes = function(node) { - for (var i = 0; i < node.dynamicEdges.length; i++) { - node.dynamicEdges[i].positionBezierNode(); - } -}; +exports.clusterByConnection = function(nodeId, options, doNotUpdateCalculationNodes) { + // kill conditions + if (nodeId === undefined) {throw new Error("No nodeId supplied to clusterByConnection!");} + if (this.nodes[nodeId] === undefined) {throw new Error("The nodeId given to clusterByConnection does not exist!");} + var node = this.nodes[nodeId]; + options = this._checkOptions(options, node); + if (options.clusterNodeProperties.x === undefined) {options.clusterNodeProperties.x = node.x; options.clusterNodeProperties.allowedToMoveX = !node.xFixed;} + if (options.clusterNodeProperties.y === undefined) {options.clusterNodeProperties.y = node.y; options.clusterNodeProperties.allowedToMoveY = !node.yFixed;} -/** - * 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) { - if (this.constants.clustering.clusterByZoom == true) { - this._formClustersByZoom(); - } - } - else { - this._forceClustersByZoom(); - } -}; + var childNodesObj = {}; + var edge; + var childEdgesObj = {} + var childNodeId; + var parentNodeId = node.id; + var parentClonedOptions = this._cloneOptions(parentNodeId); + childNodesObj[parentNodeId] = node; + // collect the nodes that will be in the cluster + for (var i = 0; i < node.edges.length; i++) { + edge = node.edges[i]; + childNodeId = this._getConnectedId(edge, parentNodeId); -/** - * This function handles the clustering by zooming out, this is based on a minimum edge distance - * - * @private - */ -exports._formClustersByZoom = function() { - var dx,dy,length; - var minLength = this.constants.clustering.clusterEdgeThreshold/this.scale; - - // check if any edges are shorter than minLength and start the clustering - // the clustering favours the node with the larger mass - for (var edgeId in this.edges) { - if (this.edges.hasOwnProperty(edgeId)) { - var edge = this.edges[edgeId]; - if (edge.connected) { - if (edge.toId != edge.fromId) { - dx = (edge.to.x - edge.from.x); - dy = (edge.to.y - edge.from.y); - length = Math.sqrt(dx * dx + dy * dy); - - - if (length < minLength) { - // first check which node is larger - var parentNode = edge.from; - var childNode = edge.to; - if (edge.to.options.mass > edge.from.options.mass) { - parentNode = edge.to; - childNode = edge.from; - } - - if (childNode.dynamicEdges.length == 1) { - this._addToCluster(parentNode,childNode,false); - } - else if (parentNode.dynamicEdges.length == 1) { - this._addToCluster(childNode,parentNode,false); - } - } - } + if (childNodeId !== parentNodeId) { + if (options.joinCondition === undefined) { + childEdgesObj[edge.id] = edge; + childNodesObj[childNodeId] = this.nodes[childNodeId]; } - } - } -}; - -/** - * This function forces the network to cluster all nodes with only one connecting edge to their - * connected node. - * - * @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.dynamicEdges.length == 1) { - var edge = childNode.dynamicEdges[0]; - var parentNode = (edge.toId == childNode.id) ? this.nodes[edge.fromId] : this.nodes[edge.toId]; - // group to the largest node - if (childNode.id != parentNode.id) { - if (parentNode.options.mass > childNode.options.mass) { - this._addToCluster(parentNode,childNode,true); - } - else { - this._addToCluster(childNode,parentNode,true); - } + else { + // clone the options and insert some additional parameters that could be interesting. + var childClonedOptions = this._cloneOptions(childNodeId); + if (options.joinCondition(parentClonedOptions, childClonedOptions) == true) { + childEdgesObj[edge.id] = edge; + childNodesObj[childNodeId] = this.nodes[childNodeId]; } } } - } -}; - - -/** - * To keep the nodes of roughly equal size we normalize the cluster levels. - * This function clusters a node to its smallest connected neighbour. - * - * @param node - * @private - */ -exports._clusterToSmallestNeighbour = function(node) { - var smallestNeighbour = -1; - var smallestNeighbourNode = null; - for (var i = 0; i < node.dynamicEdges.length; i++) { - if (node.dynamicEdges[i] !== undefined) { - var neighbour = null; - if (node.dynamicEdges[i].fromId != node.id) { - neighbour = node.dynamicEdges[i].from; - } - else if (node.dynamicEdges[i].toId != node.id) { - neighbour = node.dynamicEdges[i].to; - } - - - if (neighbour != null && smallestNeighbour > neighbour.clusterSessions.length) { - smallestNeighbour = neighbour.clusterSessions.length; - smallestNeighbourNode = neighbour; - } + else { + childEdgesObj[edge.id] = edge; } } - if (neighbour != null && this.nodes[neighbour.id] !== undefined) { - this._addToCluster(neighbour, node, true); - } -}; - - -/** - * This function forms clusters from hubs, it loops over all nodes - * - * @param {Boolean} force | Disregard zoom level - * @param {Boolean} onlyEqual | This only clusters a hub with a specific number of edges - * @private - */ -exports._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); - } - } -}; + this._cluster(childNodesObj, childEdgesObj, options, doNotUpdateCalculationNodes); +} -/** - * 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; +exports._cloneOptions = function(objId, type) { + var clonedOptions = {}; + if (type === undefined || type == 'node') { + util.deepExtend(clonedOptions, this.nodes[objId].options, true); + util.deepExtend(clonedOptions, this.nodes[objId].properties, true); + clonedOptions.amountOfConnections = this.nodes[objId].edges.length; } - //this.hubThreshold = 43 - //if (hubNode.dynamicEdgesLength < 0) { - // console.error(hubNode.dynamicEdgesLength, this.hubThreshold, onlyEqual) - //} - // we decide if the node is a hub - if ((hubNode.dynamicEdges.length >= this.hubThreshold && onlyEqual == false) || - (hubNode.dynamicEdges.length == this.hubThreshold && onlyEqual == true)) { - // initialize variables - var dx,dy,length; - var minLength = this.constants.clustering.clusterEdgeThreshold/this.scale; - var allowCluster = false; - - // we create a list of edges because the dynamicEdges change over the course of this loop - var edgesIdarray = []; - var amountOfInitialEdges = hubNode.dynamicEdges.length; - for (var j = 0; j < amountOfInitialEdges; j++) { - edgesIdarray.push(hubNode.dynamicEdges[j].id); - } - - // if the hub clustering is not forced, we check if one of the edges connected - // to a cluster is small enough based on the constants.clustering.clusterEdgeThreshold - if (force == false) { - allowCluster = false; - for (j = 0; j < amountOfInitialEdges; j++) { - var edge = this.edges[edgesIdarray[j]]; - if (edge !== undefined) { - if (edge.connected) { - if (edge.toId != edge.fromId) { - dx = (edge.to.x - edge.from.x); - dy = (edge.to.y - edge.from.y); - length = Math.sqrt(dx * dx + dy * dy); - - if (length < minLength) { - allowCluster = true; - break; - } - } - } - } + else { + util.deepExtend(clonedOptions, this.edges[objId].options, true); + util.deepExtend(clonedOptions, this.edges[objId].properties, true); + } + return clonedOptions; +} + +exports._createClusterEdges = function (childNodesObj, childEdgesObj, newEdges, options) { + var edge, childNodeId, childNode; + + var childKeys = Object.keys(childNodesObj); + for (var i = 0; i < childKeys.length; i++) { + childNodeId = childKeys[i]; + childNode = childNodesObj[childNodeId]; + + // mark all edges for removal from global and construct new edges from the cluster to others + for (var j = 0; j < childNode.edges.length; j++) { + edge = childNode.edges[j]; + childEdgesObj[edge.id] = edge; + + var otherNodeId = edge.toId; + var otherOnTo = true; + if (edge.toId != childNodeId) { + otherNodeId = edge.toId; + otherOnTo = true; } - } - - // start the clustering if allowed - if ((!force && allowCluster) || force) { - var children = []; - var childrenIds = {}; - // we loop over all edges INITIALLY connected to this hub to get a list of the childNodes - for (j = 0; j < amountOfInitialEdges; j++) { - edge = this.edges[edgesIdarray[j]]; - var childNode = this.nodes[(edge.fromId == hubNode.id) ? edge.toId : edge.fromId]; - if (childrenIds[childNode.id] === undefined) { - childrenIds[childNode.id] = true; - children.push(childNode); - } + else if (edge.fromId != childNodeId) { + otherNodeId = edge.fromId; + otherOnTo = false; } - for (j = 0; j < children.length; j++) { - var childNode = children[j]; - // 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); + if (childNodesObj[otherNodeId] === undefined) { + var clonedOptions = this._cloneOptions(edge.id, 'edge'); + util.deepExtend(clonedOptions, options.clusterEdgeProperties); + // avoid forcing the default color on edges that inherit color + if (edge.properties.color === undefined) { + delete clonedOptions.color; + } + if (otherOnTo === true) { + clonedOptions.from = options.clusterNodeProperties.id; + clonedOptions.to = otherNodeId; } else { - //console.log("WILL NOT MERGE:",childNode.dynamicEdges.length , (this.hubThreshold + absorptionSizeOffset)) + clonedOptions.from = otherNodeId; + clonedOptions.to = options.clusterNodeProperties.id; } + clonedOptions.id = 'clusterEdge:' + util.randomUUID(); + newEdges.push(new Edge(clonedOptions,this,this.constants)) } - } } -}; +} + +exports._checkOptions = function(options) { + if (options === undefined) {options = {};} + if (options.clusterEdgeProperties === undefined) {options.clusterEdgeProperties = {};} + if (options.clusterNodeProperties === undefined) {options.clusterNodeProperties = {};} + return options; +} + /** - * This function adds the child node to the parent node, creating a cluster if it is not already. * - * @param {Node} parentNode | this is the node that will house the child node - * @param {Node} childNode | this node will be deleted from the global this.nodes and stored in the parent node - * @param {Boolean} force | true will only update the remainingEdges at the very end of the clustering, ensuring single level collapse + * @param {Object} childNodesObj | object with node objects, id as keys, same as childNodes except it also contains a source node + * @param {Object} childEdgesObj | object with edge objects, id as keys + * @param {Array} options | object with {clusterNodeProperties, clusterEdgeProperties, processProperties} + * @param {Boolean} doNotUpdateCalculationNodes | when true, do not wrap up * @private */ -exports._addToCluster = function(parentNode, childNode, force) { - // join child node in the parent node - parentNode.containedNodes[childNode.id] = childNode; - //console.log(parentNode.id, childNode.id) - // 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 - //console.log("COLLECT",parentNode.id, childNode.id, edge.toId, edge.fromId) - this._addToContainedEdges(parentNode,childNode,edge); - } - else { - //console.log("REWIRE",parentNode.id, childNode.id, edge.toId, edge.fromId) - this._connectEdgeToCluster(parentNode,childNode,edge); - } - } - // a contained node has no dynamic edges. - childNode.dynamicEdges = []; +exports._cluster = function(childNodesObj, childEdgesObj, options, doNotUpdateCalculationNodes) { + // kill condition: no children so cant cluster + if (Object.keys(childNodesObj).length == 0) {return;} - // remove circular edges from clusters - this._containCircularEdgesFromNode(parentNode,childNode); + // check if we have an unique id; + if (options.clusterNodeProperties.id === undefined) {options.clusterNodeProperties.id = 'cluster:' + util.randomUUID();} + var clusterId = options.clusterNodeProperties.id; + // create the new edges that will connect to the cluster + var newEdges = []; + this._createClusterEdges(childNodesObj, childEdgesObj, newEdges, options); - // remove the childNode from the global nodes object - delete this.nodes[childNode.id]; + // construct the clusterNodeProperties + var clusterNodeProperties = options.clusterNodeProperties; + if (options.processProperties !== undefined) { + // get the childNode options + var childNodesOptions = []; + for (var nodeId in childNodesObj) { + var clonedOptions = this._cloneOptions(nodeId); + childNodesOptions.push(clonedOptions); + } - // update the properties of the child and parent - var massBefore = parentNode.options.mass; - childNode.clusterSession = this.clusterSession; - parentNode.options.mass += childNode.options.mass; - parentNode.clusterSize += childNode.clusterSize; - parentNode.options.fontSize = Math.min(this.constants.clustering.maxFontSize, this.constants.nodes.fontSize + this.constants.clustering.fontSizeMultiplier*parentNode.clusterSize); + // get clusterproperties based on childNodes + var childEdgesOptions = []; + for (var edgeId in childEdgesObj) { + var clonedOptions = this._cloneOptions(edgeId, 'edge'); + childEdgesOptions.push(clonedOptions); + } - // 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); + clusterNodeProperties = options.processProperties(clusterNodeProperties, childNodesOptions, childEdgesOptions); + if (!clusterNodeProperties) { + throw new Error("The processClusterProperties function does not return properties!"); + } } + if (clusterNodeProperties.label === undefined) { + clusterNodeProperties.label = 'cluster'; + } + - // forced clusters only open from screen size and double tap - if (force == true) { - parentNode.formationScale = 0; + // give the clusterNode a postion if it does not have one. + var pos = undefined + if (clusterNodeProperties.x === undefined) { + pos = this._getClusterPosition(childNodesObj); + clusterNodeProperties.x = pos.x; + clusterNodeProperties.allowedToMoveX = true; } - else { - parentNode.formationScale = this.scale; // The latest child has been added on this scale + if (clusterNodeProperties.x === undefined) { + if (pos === undefined) { + pos = this._getClusterPosition(childNodesObj); + } + clusterNodeProperties.y = pos.y; + clusterNodeProperties.allowedToMoveY = true; } - // 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; + // force the ID to remain the same + clusterNodeProperties.id = clusterId; - // 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); + // create the clusterNode + var clusterNode = new Node(clusterNodeProperties, this.images, this.groups, this.constants); + clusterNode.containedNodes = childNodesObj; + clusterNode.containedEdges = childEdgesObj; - // restart the simulation to reorganise all nodes - this.moving = true; -}; - -/** - * This adds an edge from the childNode to the contained edges of the parent node - * - * @param parentNode | Node object - * @param childNode | Node object - * @param edge | Edge object - * @private - */ -exports._addToContainedEdges = function(parentNode, childNode, edge) { - // create an array object if it does not yet exist for this childNode - if (parentNode.containedEdges[childNode.id] === undefined) { - parentNode.containedEdges[childNode.id] = [] + // delete contained edges from global + for (var edgeId in childEdgesObj) { + if (childEdgesObj.hasOwnProperty(edgeId)) { + if (this.edges[edgeId] !== undefined) { + if (this.edges[edgeId].via !== null) { + var viaId = this.edges[edgeId].via.id; + if (viaId) { + this.edges[edgeId].via = null + delete this.sectors['support']['nodes'][viaId]; + } + } + this.edges[edgeId].disconnect(); + delete this.edges[edgeId]; + } + } } - // add this edge to the list - parentNode.containedEdges[childNode.id].push(edge); - // remove the edge from the global edges object - delete this.edges[edge.id]; - // remove the edge from the parent object - for (var i = 0; i < parentNode.dynamicEdges.length; i++) { - if (parentNode.dynamicEdges[i].id == edge.id) { - parentNode.dynamicEdges.splice(i,1); - break; + // remove contained nodes from global + for (var nodeId in childNodesObj) { + if (childNodesObj.hasOwnProperty(nodeId)) { + this.clusteredNodes[nodeId] = {clusterId:clusterNodeProperties.id, node: this.nodes[nodeId]}; + delete this.nodes[nodeId]; } } -}; -/** - * This function connects an edge that was connected to a child node to the parent node. - * It keeps track of which nodes it has been connected to with the originalId array. - * - * @param {Node} parentNode | Node object - * @param {Node} childNode | Node object - * @param {Edge} edge | Edge object - * @private - */ -exports._connectEdgeToCluster = function(parentNode, childNode, edge) { - // handle circular edges - if (edge.toId == edge.fromId) { - this._addToContainedEdges(parentNode, childNode, edge); - } - else { - if (edge.toId == childNode.id) { // edge connected to other node on the "to" side - edge.originalToId.push(childNode.id); - edge.to = parentNode; - edge.toId = parentNode.id; - } - else { // edge connected to other node with the "from" side - edge.originalFromId.push(childNode.id); - edge.from = parentNode; - edge.fromId = parentNode.id; - } - this._addToReroutedEdges(parentNode,childNode,edge); - } -}; + // finally put the cluster node into global + this.nodes[clusterNodeProperties.id] = clusterNode; -/** - * 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 parentNode - * @param childNode - * @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); - } + // push new edges to global + for (var i = 0; i < newEdges.length; i++) { + this.edges[newEdges[i].id] = newEdges[i]; + this.edges[newEdges[i].id].connect(); } -}; -/** - * This adds an edge from the childNode to the rerouted edges of the parent node - * - * @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); + // create bezier nodes for smooth curves if needed + this._createBezierNodes(newEdges); - // this edge becomes part of the dynamicEdges of the cluster node - parentNode.dynamicEdges.push(edge); - }; + // set ID to undefined so no duplicates arise + clusterNodeProperties.id = undefined; -/** - * This function connects an edge that was connected to a cluster node back to the child node. - * - * @param parentNode | Node object - * @param childNode | Node object - * @private - */ -exports._connectEdgeBackToChild = function(parentNode, childNode) { - if (parentNode.reroutedEdges.hasOwnProperty(childNode.id)) { - for (var i = 0; i < parentNode.reroutedEdges[childNode.id].length; i++) { - var edge = parentNode.reroutedEdges[childNode.id][i]; - if (edge.originalFromId[edge.originalFromId.length-1] == childNode.id) { - edge.originalFromId.pop(); - edge.fromId = childNode.id; - edge.from = childNode; - } - else { - edge.originalToId.pop(); - edge.toId = childNode.id; - edge.to = childNode; - } - - // 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; - } - } - } - // remove the entry from the rerouted edges - delete parentNode.reroutedEdges[childNode.id]; + // wrap up + if (doNotUpdateCalculationNodes !== true) { + this._wrapUp(); } -}; +} /** - * When loops are clustered, an edge can be both in the rerouted array and the contained array. - * This function is called last to verify that all edges in dynamicEdges are in fact connected to the - * parentNode - * - * @param parentNode | Node object + * get the position of the cluster node based on what's inside + * @param {object} childNodesObj | object with node objects, id as keys + * @returns {{x: number, y: number}} * @private */ -exports._validateEdges = function(parentNode) { - var dynamicEdges = [] - for (var i = 0; i < parentNode.dynamicEdges.length; i++) { - var edge = parentNode.dynamicEdges[i]; - if (parentNode.id == edge.toId || parentNode.id == edge.fromId) { - dynamicEdges.push(edge); - } +exports._getClusterPosition = function(childNodesObj) { + var childKeys = Object.keys(childNodesObj); + var minX = childNodesObj[childKeys[0]].x; + var maxX = childNodesObj[childKeys[0]].x; + var minY = childNodesObj[childKeys[0]].y; + var maxY = childNodesObj[childKeys[0]].y; + var node; + for (var i = 0; i < childKeys.lenght; i++) { + node = childNodesObj[childKeys[0]]; + minX = node.x < minX ? node.x : minX; + maxX = node.x > maxX ? node.x : maxX; + minY = node.y < minY ? node.y : minY; + maxY = node.y > maxY ? node.y : maxY; } - parentNode.dynamicEdges = dynamicEdges; -}; + return {x: 0.5*(minX + maxX), y: 0.5*(minY + maxY)}; +} /** - * 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 + * Open a cluster by calling this function. + * @param {String} clusterNodeId | the ID of the cluster node + * @param {Boolean} doNotUpdateCalculationNodes | wrap up afterwards if not true */ -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.openCluster = function(clusterNodeId, doNotUpdateCalculationNodes) { + // kill conditions + if (clusterNodeId === undefined) {throw new Error("No clusterNodeId supplied to openCluster.");} + if (this.nodes[clusterNodeId] === undefined) {throw new Error("The clusterNodeId supplied to openCluster does not exist.");} + if (this.nodes[clusterNodeId].containedNodes === undefined) {console.log("The node:" + clusterNodeId + " is not a cluster."); return}; + var node = this.nodes[clusterNodeId]; + var containedNodes = node.containedNodes; + var containedEdges = node.containedEdges; -// ------------------- UTILITY FUNCTIONS ---------------------------- // + // release nodes + for (var nodeId in containedNodes) { + if (containedNodes.hasOwnProperty(nodeId)) { + this.nodes[nodeId] = containedNodes[nodeId]; + // inherit position + this.nodes[nodeId].x = node.x; + this.nodes[nodeId].y = node.y; + // inherit speed + this.nodes[nodeId].vx = node.vx; + this.nodes[nodeId].vy = node.vy; -/** - * This updates the node labels for all nodes (for debugging purposes) - */ -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),"]"); - } + delete this.clusteredNodes[nodeId]; } } - // 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; + // release edges + for (var edgeId in containedEdges) { + if (containedEdges.hasOwnProperty(edgeId)) { + this.edges[edgeId] = containedEdges[edgeId]; + this.edges[edgeId].connect(); + var edge = this.edges[edgeId]; + if (edge.connected === false) { + if (this.clusteredNodes[edge.fromId] !== undefined) { + this._connectEdge(edge, edge.fromId, true); } - else { - node.label = String(node.id); + if (this.clusteredNodes[edge.toId] !== undefined) { + this._connectEdge(edge, edge.toId, false); } } } } + this._createBezierNodes(containedEdges); -// /* Debug Override */ -// for (nodeId in this.nodes) { -// if (this.nodes.hasOwnProperty(nodeId)) { -// node = this.nodes[nodeId]; -// node.label = String(node.clusterSize + ":" + node.dynamicEdges.length); -// } -// } - -}; - - -/** - * 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; - - // 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;} - } + var edgeIds = []; + for (var i = 0; i < node.edges.length; i++) { + edgeIds.push(node.edges[i].id); } - 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]); - } + // remove edges in clusterNode + for (var i = 0; i < edgeIds.length; i++) { + var edge = this.edges[edgeIds[i]]; + // if the edge should have been connected to a contained node + if (edge.fromArray.length > 0 && edge.fromId == clusterNodeId) { + // the node in the from array was contained in the cluster + if (this.nodes[edge.fromArray[0].id] !== undefined) { + this._connectEdge(edge, edge.fromArray[0].id, true); } } - this._updateNodeIndexList(); - // if a cluster was formed, we increase the clusterSession - if (this.nodeIndices.length != amountOfNodes) { - this.clusterSession += 1; + else if (edge.toArray.length > 0 && edge.toId == clusterNodeId) { + // the node in the to array was contained in the cluster + if (this.nodes[edge.toArray[0].id] !== undefined) { + this._connectEdge(edge, edge.toArray[0].id, false); + } + } + else { + var edgeId = edgeIds[i]; + var viaId = this.edges[edgeId].via.id; + if (viaId) { + this.edges[edgeId].via = null + delete this.sectors['support']['nodes'][viaId]; + } + // this removes the edge from node.edges, which is why edgeIds is formed + this.edges[edgeId].disconnect(); + delete this.edges[edgeId]; } } -}; + // remove clusterNode + delete this.nodes[clusterNodeId]; + if (doNotUpdateCalculationNodes !== true) { + this._wrapUp(); + } +} -/** - * 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._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._wrapUp = function() { + this._updateNodeIndexList(); + this._updateCalculationNodes(); + this._markAllEdgesAsDirty(); + this.moving = true; + this.start(); +} +exports._connectEdge = function(edge, nodeId, from) { + var clusterStack = this._getClusterStack(nodeId); + if (from == true) { + edge.from = clusterStack[clusterStack.length - 1]; + edge.fromId = clusterStack[clusterStack.length - 1].id; + clusterStack.pop() + edge.fromArray = clusterStack; + } + else { + edge.to = clusterStack[clusterStack.length - 1]; + edge.toId = clusterStack[clusterStack.length - 1].id; + clusterStack.pop(); + edge.toArray = clusterStack; + } + edge.connect(); +} -/** - * 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. - * - */ -exports.repositionNodes = function() { - for (var i = 0; i < this.nodeIndices.length; i++) { - var node = this.nodes[this.nodeIndices[i]]; - if ((node.xFixed == false || node.yFixed == false)) { - var radius = 10 * 0.1*this.nodeIndices.length * Math.min(100,node.options.mass); - var angle = 2 * Math.PI * Math.random(); - if (node.xFixed == false) {node.x = radius * Math.cos(angle);} - if (node.yFixed == false) {node.y = radius * Math.sin(angle);} - this._repositionBezierNodes(node); - } +exports._getClusterStack = function(nodeId) { + var stack = []; + var max = 100; + var counter = 0; + + while (this.clusteredNodes[nodeId] !== undefined && counter < max) { + stack.push(this.clusteredNodes[nodeId].node); + nodeId = this.clusteredNodes[nodeId].clusterId; + counter++; } -}; + stack.push(this.nodes[nodeId]); + return stack; +} +exports._getConnectedId = function(edge, nodeId) { + if (edge.toId != nodeId) { + return edge.toId; + } + else if (edge.fromId != nodeId) { + return edge.fromId; + } + else { + return edge.fromId; + } +} + /** * 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%) @@ -1058,72 +534,27 @@ exports._getHubSize = function() { var largestHub = 0; for (var i = 0; i < this.nodeIndices.length; i++) { - var node = this.nodes[this.nodeIndices[i]]; - if (node.dynamicEdges.length > largestHub) { - largestHub = node.dynamicEdges.length; + if (node.edges.length > largestHub) { + largestHub = node.edges.length; } - average += node.dynamicEdges.length; - averageSquared += Math.pow(node.dynamicEdges.length,2); + average += node.edges.length; + averageSquared += Math.pow(node.edges.length,2); hubCounter += 1; } average = average / hubCounter; averageSquared = averageSquared / hubCounter; var variance = averageSquared - Math.pow(average,2); - var standardDeviation = Math.sqrt(variance); - this.hubThreshold = Math.floor(average + 2*standardDeviation); + var hubThreshold = Math.floor(average + 2*standardDeviation); // always have at least one to cluster - if (this.hubThreshold > largestHub) { - this.hubThreshold = largestHub; + if (hubThreshold > largestHub) { + hubThreshold = largestHub; } -// console.log("average",average,"averageSQ",averageSquared,"var",variance,"std",standardDeviation); -// console.log("hubThreshold:",this.hubThreshold); + return 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. - * - * @param {Number} fraction | between 0 and 1, the percentage of chains to reduce - * @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].dynamicEdges.length == 2) { - if (reduceAmount > 0) { - this._formClusterFromHub(this.nodes[nodeId],true,true,1); - reduceAmount -= 1; - } - } - } - } -}; - -/** - * 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._getChainFraction = function() { - var chains = 0; - var total = 0; - for (var nodeId in this.nodes) { - if (this.nodes.hasOwnProperty(nodeId)) { - if (this.nodes[nodeId].dynamicEdges.length == 2) { - chains += 1; - } - total += 1; - } - } - return chains/total; -}; diff --git a/lib/network/mixins/SelectionMixin.js b/lib/network/mixins/SelectionMixin.js index 51c1e700..7bbd0c7a 100644 --- a/lib/network/mixins/SelectionMixin.js +++ b/lib/network/mixins/SelectionMixin.js @@ -355,8 +355,8 @@ exports._clusterInSelection = function() { * @private */ exports._selectConnectedEdges = function(node) { - for (var i = 0; i < node.dynamicEdges.length; i++) { - var edge = node.dynamicEdges[i]; + for (var i = 0; i < node.edges.length; i++) { + var edge = node.edges[i]; edge.select(); this._addToSelection(edge); } @@ -369,8 +369,8 @@ exports._selectConnectedEdges = function(node) { * @private */ exports._hoverConnectedEdges = function(node) { - for (var i = 0; i < node.dynamicEdges.length; i++) { - var edge = node.dynamicEdges[i]; + for (var i = 0; i < node.edges.length; i++) { + var edge = node.edges[i]; edge.hover = true; this._addToHover(edge); } @@ -384,8 +384,8 @@ exports._hoverConnectedEdges = function(node) { * @private */ exports._unselectConnectedEdges = function(node) { - for (var i = 0; i < node.dynamicEdges.length; i++) { - var edge = node.dynamicEdges[i]; + for (var i = 0; i < node.edges.length; i++) { + var edge = node.edges[i]; edge.unselect(); this._removeFromSelection(edge); } diff --git a/lib/network/mixins/physics/HierarchialRepulsionMixin.js b/lib/network/mixins/physics/HierarchialRepulsionMixin.js index 774b4257..5797e1e3 100644 --- a/lib/network/mixins/physics/HierarchialRepulsionMixin.js +++ b/lib/network/mixins/physics/HierarchialRepulsionMixin.js @@ -81,7 +81,7 @@ exports._calculateHierarchicalSpringForces = function () { for (edgeId in edges) { if (edges.hasOwnProperty(edgeId)) { edge = edges[edgeId]; - if (edge.connected) { + if (edge.connected === true) { // only calculate forces if nodes are in the same sector if (this.nodes.hasOwnProperty(edge.toId) && this.nodes.hasOwnProperty(edge.fromId)) { edgeLength = edge.physics.springLength; diff --git a/lib/network/mixins/physics/PhysicsMixin.js b/lib/network/mixins/physics/PhysicsMixin.js index c17cacf7..c5ffd48d 100644 --- a/lib/network/mixins/physics/PhysicsMixin.js +++ b/lib/network/mixins/physics/PhysicsMixin.js @@ -71,11 +71,6 @@ exports._initializeForceCalculation = function () { 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(); } @@ -202,12 +197,10 @@ exports._calculateSpringForces = function () { for (edgeId in edges) { if (edges.hasOwnProperty(edgeId)) { edge = edges[edgeId]; - if (edge.connected) { + if (edge.connected === true) { // only calculate forces if nodes are in the same sector if (this.nodes.hasOwnProperty(edge.toId) && this.nodes.hasOwnProperty(edge.fromId)) { edgeLength = edge.physics.springLength; - // this implies that the edges between big clusters are longer - edgeLength += (edge.to.clusterSize + edge.from.clusterSize - 2) * this.constants.clustering.edgeGrowth; dx = (edge.from.x - edge.to.x); dy = (edge.from.y - edge.to.y); @@ -242,14 +235,14 @@ exports._calculateSpringForces = function () { * @private */ exports._calculateSpringForcesWithSupport = function () { - var edgeLength, edge, edgeId, combinedClusterSize; + var edgeLength, edge, edgeId; 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) { + if (edge.connected === true) { // 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) { @@ -259,10 +252,6 @@ exports._calculateSpringForcesWithSupport = function () { edgeLength = edge.physics.springLength; - combinedClusterSize = node1.clusterSize + node3.clusterSize - 2; - - // this implies that the edges between big clusters are longer - edgeLength += combinedClusterSize * this.constants.clustering.edgeGrowth; this._calculateSpringForce(node1, node2, 0.5 * edgeLength); this._calculateSpringForce(node2, node3, 0.5 * edgeLength); } diff --git a/lib/network/modules/ClusterEngine.js b/lib/network/modules/ClusterEngine.js new file mode 100644 index 00000000..0ef8e7cc --- /dev/null +++ b/lib/network/modules/ClusterEngine.js @@ -0,0 +1,17 @@ +/** + * Created by Alex on 2/20/2015. + */ + +var public = require("./clustering/public"); +var support = require("./clustering/support"); +var backend = require("./clustering/backend"); + +function ClusterEngine(network) { + this.network = network; +} + + + + + +module.exports = clusterEngine \ No newline at end of file diff --git a/lib/network/modules/clustering/backend.js b/lib/network/modules/clustering/backend.js new file mode 100644 index 00000000..e69de29b diff --git a/lib/network/modules/clustering/public.js b/lib/network/modules/clustering/public.js new file mode 100644 index 00000000..e69de29b diff --git a/lib/network/modules/clustering/support.js b/lib/network/modules/clustering/support.js new file mode 100644 index 00000000..e69de29b diff --git a/lib/timeline/component/graph2d_types/bar.js b/lib/timeline/component/graph2d_types/bar.js index 3dee4b21..1ba41365 100644 --- a/lib/timeline/component/graph2d_types/bar.js +++ b/lib/timeline/component/graph2d_types/bar.js @@ -58,7 +58,8 @@ Bargraph.draw = function (groupIds, processedGroupData, framework) { combinedData.push({ x: processedGroupData[groupIds[i]][j].x, y: processedGroupData[groupIds[i]][j].y, - groupId: groupIds[i] + groupId: groupIds[i], + label: processedGroupData[groupIds[i]][j].label }); barPoints += 1; } @@ -114,7 +115,8 @@ Bargraph.draw = function (groupIds, processedGroupData, framework) { DOMutil.drawBar(combinedData[i].x + drawData.offset, combinedData[i].y - heightOffset, drawData.width, group.zeroPosition - combinedData[i].y, group.className + ' bar', framework.svgElements, framework.svg); // draw points if (group.options.drawPoints.enabled == true) { - DOMutil.drawPoint(combinedData[i].x + drawData.offset, combinedData[i].y, group, framework.svgElements, framework.svg); + Points.draw([combinedData[i]], group, framework, drawData.offset); + //DOMutil.drawPoint(combinedData[i].x + drawData.offset, combinedData[i].y, group, framework.svgElements, framework.svg); } } }; diff --git a/lib/util.js b/lib/util.js index c4416276..bfc59ba2 100644 --- a/lib/util.js +++ b/lib/util.js @@ -225,22 +225,24 @@ exports.selectiveNotDeepExtend = function (props, a, b) { * Deep extend an object a with the properties of object b * @param {Object} a * @param {Object} b + * @param {Boolean} protoExtend --> optional parameter. If true, the prototype values will also be extended. + * (ie. the options objects that inherit from others will also get the inherited options) * @returns {Object} */ -exports.deepExtend = function(a, b) { +exports.deepExtend = function(a, b, protoExtend) { // TODO: add support for Arrays to deepExtend if (Array.isArray(b)) { throw new TypeError('Arrays are not supported by deepExtend'); } for (var prop in b) { - if (b.hasOwnProperty(prop)) { + if (b.hasOwnProperty(prop) || protoExtend === true) { if (b[prop] && b[prop].constructor === Object) { if (a[prop] === undefined) { a[prop] = {}; } if (a[prop].constructor === Object) { - exports.deepExtend(a[prop], b[prop]); + exports.deepExtend(a[prop], b[prop], protoExtend); } else { a[prop] = b[prop];