diff --git a/dist/vis.js b/dist/vis.js index 0c965926..35c9b20d 100644 --- a/dist/vis.js +++ b/dist/vis.js @@ -5,7 +5,7 @@ * A dynamic, browser-based visualization library. * * @version 4.0.0-SNAPSHOT - * @date 2015-04-14 + * @date 2015-04-15 * * @license * Copyright (C) 2011-2014 Almende B.V, http://almende.com @@ -81,9 +81,9 @@ return /******/ (function(modules) { // webpackBootstrap /* 0 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; - // utils + 'use strict'; + exports.util = __webpack_require__(1); exports.DOMutil = __webpack_require__(2); @@ -146,7 +146,7 @@ return /******/ (function(modules) { // webpackBootstrap // Deprecated since v3.0.0 exports.Graph = function () { - throw new Error("Graph is renamed to Network. Please create a graph as new vis.Network(...)"); + throw new Error('Graph is renamed to Network. Please create a graph as new vis.Network(...)'); }; // bundled external libraries @@ -158,12 +158,12 @@ return /******/ (function(modules) { // webpackBootstrap /* 1 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; - // utility functions // first check if moment.js is already loaded in the browser window, if so, // use this instance. Else, load via commonjs. + 'use strict'; + var moment = __webpack_require__(40); /** @@ -172,10 +172,9 @@ return /******/ (function(modules) { // webpackBootstrap * @return {Boolean} isNumber */ exports.isNumber = function (object) { - return object instanceof Number || typeof object == "number"; + return object instanceof Number || typeof object == 'number'; }; - exports.recursiveDOMDelete = function (DOMobject) { while (DOMobject.hasChildNodes() == true) { exports.recursiveDOMDelete(DOMobject.firstChild); @@ -207,7 +206,7 @@ return /******/ (function(modules) { // webpackBootstrap * @return {Boolean} isString */ exports.isString = function (object) { - return object instanceof String || typeof object == "string"; + return object instanceof String || typeof object == 'string'; }; /** @@ -237,7 +236,7 @@ return /******/ (function(modules) { // webpackBootstrap * @return {Boolean} isDataTable */ exports.isDataTable = function (object) { - return typeof google !== "undefined" && google.visualization && google.visualization.DataTable && object instanceof google.visualization.DataTable; + return typeof google !== 'undefined' && google.visualization && google.visualization.DataTable && object instanceof google.visualization.DataTable; }; /** @@ -246,15 +245,14 @@ return /******/ (function(modules) { // webpackBootstrap * @return {String} uuid */ exports.randomUUID = function () { - var S4 = function () { + var S4 = function S4() { return Math.floor(Math.random() * 65536 /* 65536 */ ).toString(16); }; - return S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4(); + return S4() + S4() + '-' + S4() + '-' + S4() + '-' + S4() + '-' + S4() + S4() + S4(); }; - /** * assign all keys of an object that are not nested objects to a certain value (used for color objects). * @param obj @@ -263,13 +261,27 @@ return /******/ (function(modules) { // webpackBootstrap exports.assignAllKeys = function (obj, value) { for (var prop in obj) { if (obj.hasOwnProperty(prop)) { - if (typeof obj[prop] !== "object") { + if (typeof obj[prop] !== 'object') { obj[prop] = value; } } } }; + /** + * Fill an object with a possibly partially defined other object. Only copies values. + * @param obj + * @param value + */ + exports.fillIfDefined = function (parentObj, newObj) { + for (var prop in parentObj) { + if (newObj[prop] !== undefined) { + if (typeof newObj[prop] !== 'object') { + parentObj[prop] = newObj[prop]; + } + } + } + }; /** * Extend object a with the properties of object b or a series of objects @@ -317,7 +329,7 @@ return /******/ (function(modules) { // webpackBootstrap */ exports.selectiveExtend = function (props, a, b) { if (!Array.isArray(props)) { - throw new Error("Array with property names expected as first argument"); + throw new Error('Array with property names expected as first argument'); } for (var i = 2; i < arguments.length; i++) { @@ -344,7 +356,7 @@ return /******/ (function(modules) { // webpackBootstrap exports.selectiveDeepExtend = function (props, a, b) { // TODO: add support for Arrays to deepExtend if (Array.isArray(b)) { - throw new TypeError("Arrays are not supported by deepExtend"); + throw new TypeError('Arrays are not supported by deepExtend'); } for (var i = 2; i < arguments.length; i++) { var other = arguments[i]; @@ -361,7 +373,7 @@ return /******/ (function(modules) { // webpackBootstrap a[prop] = b[prop]; } } else if (Array.isArray(b[prop])) { - throw new TypeError("Arrays are not supported by deepExtend"); + throw new TypeError('Arrays are not supported by deepExtend'); } else { a[prop] = b[prop]; } @@ -382,7 +394,7 @@ return /******/ (function(modules) { // webpackBootstrap exports.selectiveNotDeepExtend = function (props, a, b) { // TODO: add support for Arrays to deepExtend if (Array.isArray(b)) { - throw new TypeError("Arrays are not supported by deepExtend"); + throw new TypeError('Arrays are not supported by deepExtend'); } for (var prop in b) { if (b.hasOwnProperty(prop)) { @@ -397,7 +409,7 @@ return /******/ (function(modules) { // webpackBootstrap a[prop] = b[prop]; } } else if (Array.isArray(b[prop])) { - throw new TypeError("Arrays are not supported by deepExtend"); + throw new TypeError('Arrays are not supported by deepExtend'); } else { a[prop] = b[prop]; } @@ -418,7 +430,7 @@ return /******/ (function(modules) { // webpackBootstrap 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"); + throw new TypeError('Arrays are not supported by deepExtend'); } for (var prop in b) { @@ -433,7 +445,7 @@ return /******/ (function(modules) { // webpackBootstrap a[prop] = b[prop]; } } else if (Array.isArray(b[prop])) { - throw new TypeError("Arrays are not supported by deepExtend"); + throw new TypeError('Arrays are not supported by deepExtend'); } else { a[prop] = b[prop]; } @@ -481,25 +493,25 @@ return /******/ (function(modules) { // webpackBootstrap if (!type) { return object; } - if (!(typeof type === "string") && !(type instanceof String)) { - throw new Error("Type must be a string"); + if (!(typeof type === 'string') && !(type instanceof String)) { + throw new Error('Type must be a string'); } //noinspection FallthroughInSwitchStatementJS switch (type) { - case "boolean": - case "Boolean": + case 'boolean': + case 'Boolean': return Boolean(object); - case "number": - case "Number": + case 'number': + case 'Number': return Number(object.valueOf()); - case "string": - case "String": + case 'string': + case 'String': return String(object); - case "Date": + case 'Date': if (exports.isNumber(object)) { return new Date(object); } @@ -517,10 +529,10 @@ return /******/ (function(modules) { // webpackBootstrap return moment(object).toDate(); // parse string } } else { - throw new Error("Cannot convert object of type " + exports.getType(object) + " to type Date"); + throw new Error('Cannot convert object of type ' + exports.getType(object) + ' to type Date'); } - case "Moment": + case 'Moment': if (exports.isNumber(object)) { return moment(object); } @@ -538,10 +550,10 @@ return /******/ (function(modules) { // webpackBootstrap return moment(object); // parse string } } else { - throw new Error("Cannot convert object of type " + exports.getType(object) + " to type Date"); + throw new Error('Cannot convert object of type ' + exports.getType(object) + ' to type Date'); } - case "ISODate": + case 'ISODate': if (exports.isNumber(object)) { return new Date(object); } else if (object instanceof Date) { @@ -557,14 +569,14 @@ return /******/ (function(modules) { // webpackBootstrap return new Date(object).toISOString(); // parse string } } else { - throw new Error("Cannot convert object of type " + exports.getType(object) + " to type ISODate"); + throw new Error('Cannot convert object of type ' + exports.getType(object) + ' to type ISODate'); } - case "ASPDate": + case 'ASPDate': if (exports.isNumber(object)) { - return "/Date(" + object + ")/"; + return '/Date(' + object + ')/'; } else if (object instanceof Date) { - return "/Date(" + object.valueOf() + ")/"; + return '/Date(' + object.valueOf() + ')/'; } else if (exports.isString(object)) { match = ASPDateRegex.exec(object); var value; @@ -574,13 +586,13 @@ return /******/ (function(modules) { // webpackBootstrap } else { value = new Date(object).valueOf(); // parse string } - return "/Date(" + value + ")/"; + return '/Date(' + value + ')/'; } else { - throw new Error("Cannot convert object of type " + exports.getType(object) + " to type ASPDate"); + throw new Error('Cannot convert object of type ' + exports.getType(object) + ' to type ASPDate'); } default: - throw new Error("Unknown type \"" + type + "\""); + throw new Error('Unknown type "' + type + '"'); } }; @@ -597,32 +609,32 @@ return /******/ (function(modules) { // webpackBootstrap exports.getType = function (object) { var type = typeof object; - if (type == "object") { + if (type == 'object') { if (object == null) { - return "null"; + return 'null'; } if (object instanceof Boolean) { - return "Boolean"; + return 'Boolean'; } if (object instanceof Number) { - return "Number"; + return 'Number'; } if (object instanceof String) { - return "String"; + return 'String'; } if (Array.isArray(object)) { - return "Array"; + return 'Array'; } if (object instanceof Date) { - return "Date"; + return 'Date'; } - return "Object"; - } else if (type == "number") { - return "Number"; - } else if (type == "boolean") { - return "Boolean"; - } else if (type == "string") { - return "String"; + return 'Object'; + } else if (type == 'number') { + return 'Number'; + } else if (type == 'boolean') { + return 'Boolean'; + } else if (type == 'string') { + return 'String'; } return type; @@ -654,10 +666,10 @@ return /******/ (function(modules) { // webpackBootstrap * @param {String} className */ exports.addClassName = function (elem, className) { - var classes = elem.className.split(" "); + var classes = elem.className.split(' '); if (classes.indexOf(className) == -1) { classes.push(className); // add the class to the array - elem.className = classes.join(" "); + elem.className = classes.join(' '); } }; @@ -667,11 +679,11 @@ return /******/ (function(modules) { // webpackBootstrap * @param {String} className */ exports.removeClassName = function (elem, className) { - var classes = elem.className.split(" "); + var classes = elem.className.split(' '); var index = classes.indexOf(className); if (index != -1) { classes.splice(index, 1); // remove the class from the array - elem.className = classes.join(" "); + elem.className = classes.join(' '); } }; @@ -745,13 +757,13 @@ return /******/ (function(modules) { // webpackBootstrap if (element.addEventListener) { if (useCapture === undefined) useCapture = false; - if (action === "mousewheel" && navigator.userAgent.indexOf("Firefox") >= 0) { - action = "DOMMouseScroll"; // For Firefox + if (action === 'mousewheel' && navigator.userAgent.indexOf('Firefox') >= 0) { + action = 'DOMMouseScroll'; // For Firefox } element.addEventListener(action, listener, useCapture); } else { - element.attachEvent("on" + action, listener); // IE browsers + element.attachEvent('on' + action, listener); // IE browsers } }; @@ -767,14 +779,14 @@ return /******/ (function(modules) { // webpackBootstrap // non-IE browsers if (useCapture === undefined) useCapture = false; - if (action === "mousewheel" && navigator.userAgent.indexOf("Firefox") >= 0) { - action = "DOMMouseScroll"; // For Firefox + if (action === 'mousewheel' && navigator.userAgent.indexOf('Firefox') >= 0) { + action = 'DOMMouseScroll'; // For Firefox } element.removeEventListener(action, listener, useCapture); } else { // IE browsers - element.detachEvent("on" + action, listener); + element.detachEvent('on' + action, listener); } }; @@ -827,7 +839,7 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {Boolean} bool */ exports.option.asBoolean = function (value, defaultValue) { - if (typeof value == "function") { + if (typeof value == 'function') { value = value(); } @@ -845,7 +857,7 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {Number} number */ exports.option.asNumber = function (value, defaultValue) { - if (typeof value == "function") { + if (typeof value == 'function') { value = value(); } @@ -863,7 +875,7 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {String} str */ exports.option.asString = function (value, defaultValue) { - if (typeof value == "function") { + if (typeof value == 'function') { value = value(); } @@ -881,14 +893,14 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {String} size */ exports.option.asSize = function (value, defaultValue) { - if (typeof value == "function") { + if (typeof value == 'function') { value = value(); } if (exports.isString(value)) { return value; } else if (exports.isNumber(value)) { - return value + "px"; + return value + 'px'; } else { return defaultValue || null; } @@ -901,7 +913,7 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {HTMLElement | null} dom */ exports.option.asElement = function (value, defaultValue) { - if (typeof value == "function") { + if (typeof value == 'function') { value = value(); } @@ -935,15 +947,15 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {*} */ exports.overrideOpacity = function (color, opacity) { - if (color.indexOf("rgb") != -1) { - var rgb = color.substr(color.indexOf("(") + 1).replace(")", "").split(","); - return "rgba(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + "," + opacity + ")"; + if (color.indexOf('rgb') != -1) { + var rgb = color.substr(color.indexOf('(') + 1).replace(')', '').split(','); + return 'rgba(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ',' + opacity + ')'; } else { var rgb = exports.hexToRGB(color); if (rgb == null) { return color; } else { - return "rgba(" + rgb.r + "," + rgb.g + "," + rgb.b + "," + opacity + ")"; + return 'rgba(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ',' + opacity + ')'; } } }; @@ -957,7 +969,7 @@ return /******/ (function(modules) { // webpackBootstrap * @constructor */ exports.RGBToHex = function (red, green, blue) { - return "#" + ((1 << 24) + (red << 16) + (green << 8) + blue).toString(16).slice(1); + return '#' + ((1 << 24) + (red << 16) + (green << 8) + blue).toString(16).slice(1); }; /** @@ -970,7 +982,7 @@ return /******/ (function(modules) { // webpackBootstrap var c; if (exports.isString(color)) { if (exports.isValidRGB(color)) { - var rgb = color.substr(4).substr(0, color.length - 5).split(","); + var rgb = color.substr(4).substr(0, color.length - 5).split(','); color = exports.RGBToHex(rgb[0], rgb[1], rgb[2]); } if (exports.isValidHex(color)) { @@ -1067,12 +1079,12 @@ return /******/ (function(modules) { // webpackBootstrap var cssUtil = { // split a string with css styles into an object with key/values - split: function (cssText) { + split: function split(cssText) { var styles = {}; - cssText.split(";").forEach(function (style) { - if (style.trim() != "") { - var parts = style.split(":"); + cssText.split(';').forEach(function (style) { + if (style.trim() != '') { + var parts = style.split(':'); var key = parts[0].trim(); var value = parts[1].trim(); styles[key] = value; @@ -1083,10 +1095,10 @@ return /******/ (function(modules) { // webpackBootstrap }, // build a css text string from an object with key/values - join: function (styles) { + join: function join(styles) { return Object.keys(styles).map(function (key) { - return key + ": " + styles[key]; - }).join("; "); + return key + ': ' + styles[key]; + }).join('; '); } }; @@ -1172,12 +1184,12 @@ return /******/ (function(modules) { // webpackBootstrap }; exports.isValidRGB = function (rgb) { - rgb = rgb.replace(" ", ""); + rgb = rgb.replace(' ', ''); var isOk = /rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)/i.test(rgb); return isOk; }; exports.isValidRGBA = function (rgba) { - rgba = rgba.replace(" ", ""); + rgba = rgba.replace(' ', ''); var isOk = /rgba\((\d{1,3}),(\d{1,3}),(\d{1,3}),(.{1,3})\)/i.test(rgba); return isOk; }; @@ -1190,11 +1202,11 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {*} */ exports.selectiveBridgeObject = function (fields, referenceObject) { - if (typeof referenceObject == "object") { + if (typeof referenceObject == 'object') { var objectTo = Object.create(referenceObject); for (var i = 0; i < fields.length; i++) { if (referenceObject.hasOwnProperty(fields[i])) { - if (typeof referenceObject[fields[i]] == "object") { + if (typeof referenceObject[fields[i]] == 'object') { objectTo[fields[i]] = exports.bridgeObject(referenceObject[fields[i]]); } } @@ -1213,11 +1225,11 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {*} */ exports.bridgeObject = function (referenceObject) { - if (typeof referenceObject == "object") { + if (typeof referenceObject == 'object') { var objectTo = Object.create(referenceObject); for (var i in referenceObject) { if (referenceObject.hasOwnProperty(i)) { - if (typeof referenceObject[i] == "object") { + if (typeof referenceObject[i] == 'object') { objectTo[i] = exports.bridgeObject(referenceObject[i]); } } @@ -1228,7 +1240,6 @@ return /******/ (function(modules) { // webpackBootstrap } }; - /** * this is used to set the options of subobjects in the options object. A requirement of these subobjects * is that they have an 'enabled' element which is optional for the user but mandatory for the program. @@ -1240,7 +1251,7 @@ return /******/ (function(modules) { // webpackBootstrap */ exports.mergeOptions = function (mergeTarget, options, option) { if (options[option] !== undefined) { - if (typeof options[option] == "boolean") { + if (typeof options[option] == 'boolean') { mergeTarget[option].enabled = options[option]; } else { mergeTarget[option].enabled = true; @@ -1253,7 +1264,6 @@ return /******/ (function(modules) { // webpackBootstrap } }; - /** * This function does a binary search for a visible item in a sorted list. If we find a visible item, the code that uses * this function will then iterate in both directions over this sorted list to find all visible items. @@ -1326,10 +1336,10 @@ return /******/ (function(modules) { // webpackBootstrap return middle; } else if (prevValue < target && value > target) { // target is in between of the previous and the current - return sidePreference == "before" ? Math.max(0, middle - 1) : middle; + return sidePreference == 'before' ? Math.max(0, middle - 1) : middle; } else if (value < target && nextValue > target) { // target is in between of the current and the next - return sidePreference == "before" ? middle : Math.min(orderedItems.length - 1, middle + 1); + return sidePreference == 'before' ? middle : Math.min(orderedItems.length - 1, middle + 1); } else { // didnt find the target, we need to change our boundaries. if (value < target) { @@ -1364,8 +1374,6 @@ return /******/ (function(modules) { // webpackBootstrap return -change / 2 * (t * (t - 2) - 1) + start; }; - - /* * Easing Functions - inspired from http://gizma.com/easing/ * only considering the t value for the range [0, 1] => [0, 1] @@ -1373,55 +1381,55 @@ return /******/ (function(modules) { // webpackBootstrap */ exports.easingFunctions = { // no easing, no acceleration - linear: function (t) { + linear: function linear(t) { return t; }, // accelerating from zero velocity - easeInQuad: function (t) { + easeInQuad: function easeInQuad(t) { return t * t; }, // decelerating to zero velocity - easeOutQuad: function (t) { + easeOutQuad: function easeOutQuad(t) { return t * (2 - t); }, // acceleration until halfway, then deceleration - easeInOutQuad: function (t) { + easeInOutQuad: function easeInOutQuad(t) { return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t; }, // accelerating from zero velocity - easeInCubic: function (t) { + easeInCubic: function easeInCubic(t) { return t * t * t; }, // decelerating to zero velocity - easeOutCubic: function (t) { + easeOutCubic: function easeOutCubic(t) { return --t * t * t + 1; }, // acceleration until halfway, then deceleration - easeInOutCubic: function (t) { + easeInOutCubic: function easeInOutCubic(t) { return t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1; }, // accelerating from zero velocity - easeInQuart: function (t) { + easeInQuart: function easeInQuart(t) { return t * t * t * t; }, // decelerating to zero velocity - easeOutQuart: function (t) { + easeOutQuart: function easeOutQuart(t) { return 1 - --t * t * t * t; }, // acceleration until halfway, then deceleration - easeInOutQuart: function (t) { + easeInOutQuart: function easeInOutQuart(t) { return t < 0.5 ? 8 * t * t * t * t : 1 - 8 * --t * t * t * t; }, // accelerating from zero velocity - easeInQuint: function (t) { + easeInQuint: function easeInQuint(t) { return t * t * t * t * t; }, // decelerating to zero velocity - easeOutQuint: function (t) { + easeOutQuint: function easeOutQuint(t) { return 1 + --t * t * t * t * t; }, // acceleration until halfway, then deceleration - easeInOutQuint: function (t) { + easeInOutQuint: function easeInOutQuint(t) { return t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * --t * t * t * t * t; } }; @@ -1430,8 +1438,6 @@ return /******/ (function(modules) { // webpackBootstrap /* 2 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; - // DOM utility methods /** @@ -1439,6 +1445,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param JSONcontainer * @private */ + 'use strict'; + exports.prepareElements = function (JSONcontainer) { // cleanup the redundant svgElements; for (var elementType in JSONcontainer) { @@ -1491,12 +1499,12 @@ return /******/ (function(modules) { // webpackBootstrap 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); + 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); + element = document.createElementNS('http://www.w3.org/2000/svg', elementType); JSONcontainer[elementType] = { used: [], redundant: [] }; svgContainer.appendChild(element); } @@ -1504,7 +1512,6 @@ return /******/ (function(modules) { // webpackBootstrap 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. @@ -1547,9 +1554,6 @@ return /******/ (function(modules) { // webpackBootstrap 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 @@ -1565,25 +1569,25 @@ return /******/ (function(modules) { // webpackBootstrap */ 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); + 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); + 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 (group.options.drawPoints.styles !== undefined) { - point.setAttributeNS(null, "style", group.group.options.drawPoints.styles); + point.setAttributeNS(null, 'style', group.group.options.drawPoints.styles); } - point.setAttributeNS(null, "class", group.className + " point"); + point.setAttributeNS(null, 'class', group.className + ' point'); //handle label - var label = exports.getSVGElement("text", JSONcontainer, svgContainer); + var label = exports.getSVGElement('text', JSONcontainer, svgContainer); if (labelObj) { if (labelObj.xOffset) { x = x + labelObj.xOffset; @@ -1597,12 +1601,11 @@ return /******/ (function(modules) { // webpackBootstrap } if (labelObj.className) { - label.setAttributeNS(null, "class", labelObj.className + " label"); + label.setAttributeNS(null, 'class', labelObj.className + ' label'); } - } - label.setAttributeNS(null, "x", x); - label.setAttributeNS(null, "y", y); + label.setAttributeNS(null, 'x', x); + label.setAttributeNS(null, 'y', y); return point; }; @@ -1619,12 +1622,12 @@ return /******/ (function(modules) { // webpackBootstrap 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 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); } }; @@ -1632,7 +1635,7 @@ return /******/ (function(modules) { // webpackBootstrap /* 3 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; var util = __webpack_require__(1); var Queue = __webpack_require__(5); @@ -1690,7 +1693,7 @@ return /******/ (function(modules) { // webpackBootstrap 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._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 @@ -1699,8 +1702,8 @@ return /******/ (function(modules) { // webpackBootstrap 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"; + if (value == 'Date' || value == 'ISODate' || value == 'ASPDate') { + this._type[field] = 'Date'; } else { this._type[field] = value; } @@ -1710,7 +1713,7 @@ return /******/ (function(modules) { // webpackBootstrap // 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."); + throw new Error('Option "convert" is deprecated. Use "type" instead.'); } this._subscribers = {}; // event subscribers @@ -1744,11 +1747,11 @@ return /******/ (function(modules) { // webpackBootstrap // create queue and update its options if (!this._queue) { this._queue = Queue.extend(this, { - replace: ["add", "update", "remove"] + replace: ['add', 'update', 'remove'] }); } - if (typeof options.queue === "object") { + if (typeof options.queue === 'object') { this._queue.setOptions(options.queue); } } @@ -1804,16 +1807,16 @@ return /******/ (function(modules) { // webpackBootstrap * @private */ DataSet.prototype._trigger = function (event, params, senderId) { - if (event == "*") { - throw new Error("Cannot trigger event *"); + if (event == '*') { + throw new Error('Cannot trigger event *'); } var subscribers = []; if (event in this._subscribers) { subscribers = subscribers.concat(this._subscribers[event]); } - if ("*" in this._subscribers) { - subscribers = subscribers.concat(this._subscribers["*"]); + if ('*' in this._subscribers) { + subscribers = subscribers.concat(this._subscribers['*']); } for (var i = 0; i < subscribers.length; i++) { @@ -1860,11 +1863,11 @@ return /******/ (function(modules) { // webpackBootstrap id = me._addItem(data); addedIds.push(id); } else { - throw new Error("Unknown dataType"); + throw new Error('Unknown dataType'); } if (addedIds.length) { - this._trigger("add", { items: addedIds }, senderId); + this._trigger('add', { items: addedIds }, senderId); } return addedIds; @@ -1883,7 +1886,7 @@ return /******/ (function(modules) { // webpackBootstrap var me = this; var fieldId = me._fieldId; - var addOrUpdate = function (item) { + var addOrUpdate = function addOrUpdate(item) { var id = item[fieldId]; if (me._data[id]) { // update item @@ -1918,14 +1921,14 @@ return /******/ (function(modules) { // webpackBootstrap // Single item addOrUpdate(data); } else { - throw new Error("Unknown dataType"); + throw new Error('Unknown dataType'); } if (addedIds.length) { - this._trigger("add", { items: addedIds }, senderId); + this._trigger('add', { items: addedIds }, senderId); } if (updatedIds.length) { - this._trigger("update", { items: updatedIds, data: updatedData }, senderId); + this._trigger('update', { items: updatedIds, data: updatedData }, senderId); } return addedIds.concat(updatedIds); @@ -1972,12 +1975,12 @@ return /******/ (function(modules) { // webpackBootstrap // parse the arguments var id, ids, options, data; var firstType = util.getType(arguments[0]); - if (firstType == "String" || firstType == "Number") { + if (firstType == 'String' || firstType == 'Number') { // get(id [, options] [, data]) id = arguments[0]; options = arguments[1]; data = arguments[2]; - } else if (firstType == "Array") { + } else if (firstType == 'Array') { // get(ids [, options] [, data]) ids = arguments[0]; options = arguments[1]; @@ -1991,19 +1994,19 @@ return /******/ (function(modules) { // webpackBootstrap // determine the return type var returnType; if (options && options.returnType) { - var allowedValues = ["DataTable", "Array", "Object"]; - returnType = allowedValues.indexOf(options.returnType) == -1 ? "Array" : options.returnType; + var allowedValues = ['DataTable', 'Array', 'Object']; + returnType = allowedValues.indexOf(options.returnType) == -1 ? 'Array' : options.returnType; 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 + ")"); + 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\""); + 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"; + returnType = util.getType(data) == 'DataTable' ? 'DataTable' : 'Array'; } else { - returnType = "Array"; + returnType = 'Array'; } // build options @@ -2060,7 +2063,7 @@ return /******/ (function(modules) { // webpackBootstrap } // return the results - if (returnType == "DataTable") { + if (returnType == 'DataTable') { var columns = this._getColumnNames(data); if (id != undefined) { // append a single item to the data table @@ -2072,7 +2075,7 @@ return /******/ (function(modules) { // webpackBootstrap } } return data; - } else if (returnType == "Object") { + } else if (returnType == 'Object') { var result = {}; for (i = 0; i < items.length; i++) { result[items[i].id] = items[i]; @@ -2301,14 +2304,14 @@ return /******/ (function(modules) { // webpackBootstrap var bv = b[name]; return av > bv ? 1 : av < bv ? -1 : 0; }); - } else if (typeof order === "function") { + } 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"); + throw new TypeError('Order must be a function or a string'); } }; @@ -2340,7 +2343,7 @@ return /******/ (function(modules) { // webpackBootstrap } if (removedIds.length) { - this._trigger("remove", { items: removedIds }, senderId); + this._trigger('remove', { items: removedIds }, senderId); } return removedIds; @@ -2381,7 +2384,7 @@ return /******/ (function(modules) { // webpackBootstrap this._data = {}; this.length = 0; - this._trigger("remove", { items: ids }, senderId); + this._trigger('remove', { items: ids }, senderId); return ids; }; @@ -2488,7 +2491,7 @@ return /******/ (function(modules) { // webpackBootstrap // 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"); + throw new Error('Cannot add item: item with id ' + id + ' already exists'); } } else { // generate an id @@ -2557,12 +2560,12 @@ return /******/ (function(modules) { // webpackBootstrap 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) + ")"); + 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"); + throw new Error('Cannot update item: no item with id ' + id + ' found'); } // merge with current item @@ -2612,7 +2615,7 @@ return /******/ (function(modules) { // webpackBootstrap /* 4 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; var util = __webpack_require__(1); var DataSet = __webpack_require__(3); @@ -2632,7 +2635,7 @@ return /******/ (function(modules) { // webpackBootstrap 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._fieldId = 'id'; // name of the field containing id this._subscribers = {}; // event subscribers var me = this; @@ -2656,7 +2659,7 @@ return /******/ (function(modules) { // webpackBootstrap if (this._data) { // unsubscribe from current dataset if (this._data.unsubscribe) { - this._data.unsubscribe("*", this.listener); + this._data.unsubscribe('*', this.listener); } // trigger a remove of all items in memory @@ -2668,14 +2671,14 @@ return /******/ (function(modules) { // webpackBootstrap } this._ids = {}; this.length = 0; - this._trigger("remove", { items: ids }); + this._trigger('remove', { items: ids }); } this._data = data; if (this._data) { // update fieldId - this._fieldId = this._options.fieldId || this._data && this._data.options && this._data.options.fieldId || "id"; + 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 }); @@ -2684,11 +2687,11 @@ return /******/ (function(modules) { // webpackBootstrap this._ids[id] = true; } this.length = ids.length; - this._trigger("add", { items: ids }); + this._trigger('add', { items: ids }); // subscribe to new dataset if (this._data.on) { - this._data.on("*", this.listener); + this._data.on('*', this.listener); } } }; @@ -2728,10 +2731,10 @@ return /******/ (function(modules) { // webpackBootstrap // trigger events if (added.length) { - this._trigger("add", { items: added }); + this._trigger('add', { items: added }); } if (removed.length) { - this._trigger("remove", { items: removed }); + this._trigger('remove', { items: removed }); } }; @@ -2775,7 +2778,7 @@ return /******/ (function(modules) { // webpackBootstrap // parse the arguments var ids, options, data; var firstType = util.getType(arguments[0]); - if (firstType == "String" || firstType == "Number" || firstType == "Array") { + 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]; @@ -2880,7 +2883,7 @@ return /******/ (function(modules) { // webpackBootstrap if (ids && data) { switch (event) { - case "add": + case 'add': // filter the ids of the added items for (i = 0, len = ids.length; i < len; i++) { id = ids[i]; @@ -2893,7 +2896,7 @@ return /******/ (function(modules) { // webpackBootstrap break; - case "update": + 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++) { @@ -2917,7 +2920,7 @@ return /******/ (function(modules) { // webpackBootstrap break; - case "remove": + case 'remove': // filter the ids of the removed items for (i = 0, len = ids.length; i < len; i++) { id = ids[i]; @@ -2933,13 +2936,13 @@ return /******/ (function(modules) { // webpackBootstrap this.length += added.length - removed.length; if (added.length) { - this._trigger("add", { items: added }, senderId); + this._trigger('add', { items: added }, senderId); } if (updated.length) { - this._trigger("update", { items: updated }, senderId); + this._trigger('update', { items: updated }, senderId); } if (removed.length) { - this._trigger("remove", { items: removed }, senderId); + this._trigger('remove', { items: removed }, senderId); } } }; @@ -2954,14 +2957,13 @@ return /******/ (function(modules) { // webpackBootstrap DataView.prototype.unsubscribe = DataView.prototype.off; module.exports = DataView; + // nothing interesting for me :-( /***/ }, /* 5 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; - /** * A queue * @param {Object} options @@ -2975,6 +2977,8 @@ return /******/ (function(modules) { // webpackBootstrap * Default value of max is Infinity. * @constructor */ + 'use strict'; + function Queue(options) { // options this.delay = null; @@ -3002,10 +3006,10 @@ return /******/ (function(modules) { // webpackBootstrap * @param options */ Queue.prototype.setOptions = function (options) { - if (options && typeof options.delay !== "undefined") { + if (options && typeof options.delay !== 'undefined') { this.delay = options.delay; } - if (options && typeof options.max !== "undefined") { + if (options && typeof options.max !== 'undefined') { this.max = options.max; } @@ -3035,14 +3039,14 @@ return /******/ (function(modules) { // webpackBootstrap var queue = new Queue(options); if (object.flush !== undefined) { - throw new Error("Target object already has a property flush"); + throw new Error('Target object already has a property flush'); } object.flush = function () { queue.flush(); }; var methods = [{ - name: "flush", + name: 'flush', original: undefined }]; @@ -3096,7 +3100,7 @@ return /******/ (function(modules) { // webpackBootstrap var me = this; var original = object[method]; if (!original) { - throw new Error("Method " + method + " undefined"); + throw new Error('Method ' + method + ' undefined'); } object[method] = function () { @@ -3120,7 +3124,7 @@ return /******/ (function(modules) { // webpackBootstrap * @param {function | {fn: function, args: Array} | {fn: function, args: Array, context: Object}} entry */ Queue.prototype.queue = function (entry) { - if (typeof entry === "function") { + if (typeof entry === 'function') { this._queue.push({ fn: entry }); } else { this._queue.push(entry); @@ -3141,7 +3145,7 @@ return /******/ (function(modules) { // webpackBootstrap // flush after a period of inactivity when a delay is configured clearTimeout(this._timeout); - if (this.queue.length > 0 && typeof this.delay === "number") { + if (this.queue.length > 0 && typeof this.delay === 'number') { var me = this; this._timeout = setTimeout(function () { me.flush(); @@ -3165,7 +3169,7 @@ return /******/ (function(modules) { // webpackBootstrap /* 6 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; var Emitter = __webpack_require__(42); var DataSet = __webpack_require__(3); @@ -3191,30 +3195,30 @@ return /******/ (function(modules) { // webpackBootstrap */ function Graph3d(container, data, options) { if (!(this instanceof Graph3d)) { - throw new SyntaxError("Constructor must be called with the new operator"); + throw new SyntaxError('Constructor must be called with the new operator'); } // create variables and set default values this.containerElement = container; - this.width = "400px"; - this.height = "400px"; + this.width = '400px'; + this.height = '400px'; this.margin = 10; // px - this.defaultXCenter = "55%"; - this.defaultYCenter = "50%"; + this.defaultXCenter = '55%'; + this.defaultYCenter = '50%'; - this.xLabel = "x"; - this.yLabel = "y"; - this.zLabel = "z"; + this.xLabel = 'x'; + this.yLabel = 'y'; + this.zLabel = 'z'; - var passValueFn = function (v) { + var passValueFn = function passValueFn(v) { return v; }; this.xValueLabel = passValueFn; this.yValueLabel = passValueFn; this.zValueLabel = passValueFn; - this.filterLabel = "time"; - this.legendLabel = "value"; + this.filterLabel = 'time'; + this.legendLabel = 'value'; this.style = Graph3d.STYLE.DOT; this.showPerspective = true; @@ -3257,10 +3261,10 @@ return /******/ (function(modules) { // webpackBootstrap // TODO: customize axis range // constants - this.colorAxis = "#4D4D4D"; - this.colorGrid = "#D3D3D3"; - this.colorDot = "#7DC1FF"; - this.colorDotBorder = "#3267D2"; + this.colorAxis = '#4D4D4D'; + this.colorGrid = '#D3D3D3'; + this.colorDot = '#7DC1FF'; + this.colorDotBorder = '#3267D2'; // create a frame and canvas this.create(); @@ -3308,7 +3312,6 @@ return /******/ (function(modules) { // webpackBootstrap this.camera.setArmLocation(xCenter, yCenter, zCenter); }; - /** * Convert a 3D location to a 2D location on screen * http://en.wikipedia.org/wiki/3D_projection @@ -3336,7 +3339,6 @@ return /******/ (function(modules) { // webpackBootstrap cy = this.camera.getCameraLocation().y, cz = this.camera.getCameraLocation().z, - // calculate angles sinTx = Math.sin(this.camera.getCameraRotation().x), cosTx = Math.cos(this.camera.getCameraRotation().x), @@ -3345,7 +3347,6 @@ return /******/ (function(modules) { // webpackBootstrap sinTz = Math.sin(this.camera.getCameraRotation().z), cosTz = Math.cos(this.camera.getCameraRotation().z), - // 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)), @@ -3390,29 +3391,28 @@ return /******/ (function(modules) { // webpackBootstrap * @param {string | {fill: string, stroke: string, strokeWidth: string}} backgroundColor */ Graph3d.prototype._setBackgroundColor = function (backgroundColor) { - var fill = "white"; - var stroke = "gray"; + var fill = 'white'; + var stroke = 'gray'; var strokeWidth = 1; - if (typeof backgroundColor === "string") { + if (typeof backgroundColor === 'string') { fill = backgroundColor; - stroke = "none"; + stroke = 'none'; strokeWidth = 0; - } else if (typeof backgroundColor === "object") { + } 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) {} else { - throw "Unsupported type of backgroundColor"; + 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"; + this.frame.style.borderWidth = strokeWidth + 'px'; + this.frame.style.borderStyle = 'solid'; }; - /// enumerate the available styles Graph3d.STYLE = { BAR: 0, @@ -3435,25 +3435,25 @@ return /******/ (function(modules) { // webpackBootstrap */ Graph3d.prototype._getStyleNumber = function (styleName) { switch (styleName) { - case "dot": + case 'dot': return Graph3d.STYLE.DOT; - case "dot-line": + case 'dot-line': return Graph3d.STYLE.DOTLINE; - case "dot-color": + case 'dot-color': return Graph3d.STYLE.DOTCOLOR; - case "dot-size": + case 'dot-size': return Graph3d.STYLE.DOTSIZE; - case "line": + case 'line': return Graph3d.STYLE.LINE; - case "grid": + case 'grid': return Graph3d.STYLE.GRID; - case "surface": + case 'surface': return Graph3d.STYLE.SURFACE; - case "bar": + case 'bar': return Graph3d.STYLE.BAR; - case "bar-color": + case 'bar-color': return Graph3d.STYLE.BARCOLOR; - case "bar-size": + case 'bar-size': return Graph3d.STYLE.BARSIZE; } @@ -3487,7 +3487,7 @@ return /******/ (function(modules) { // webpackBootstrap this.colFilter = 4; } } else { - throw "Unknown style \"" + this.style + "\""; + throw 'Unknown style "' + this.style + '"'; } }; @@ -3495,7 +3495,6 @@ return /******/ (function(modules) { // webpackBootstrap return data.length; }; - Graph3d.prototype.getNumberOfColumns = function (data) { var counter = 0; for (var column in data[0]) { @@ -3506,7 +3505,6 @@ return /******/ (function(modules) { // webpackBootstrap return counter; }; - Graph3d.prototype.getDistinctValues = function (data, column) { var distinctValues = []; for (var i = 0; i < data.length; i++) { @@ -3517,7 +3515,6 @@ return /******/ (function(modules) { // webpackBootstrap 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++) { @@ -3542,7 +3539,7 @@ return /******/ (function(modules) { // webpackBootstrap // unsubscribe from the dataTable if (this.dataSet) { - this.dataSet.off("*", this._onChange); + this.dataSet.off('*', this._onChange); } if (rawData === undefined) return; @@ -3555,7 +3552,7 @@ return /******/ (function(modules) { // webpackBootstrap if (rawData instanceof DataSet || rawData instanceof DataView) { data = rawData.get(); } else { - throw new Error("Array, DataSet, or DataView expected"); + throw new Error('Array, DataSet, or DataView expected'); } if (data.length == 0) return; @@ -3567,7 +3564,7 @@ return /******/ (function(modules) { // webpackBootstrap this._onChange = function () { me.setData(me.dataSet); }; - this.dataSet.on("*", this._onChange); + this.dataSet.on('*', this._onChange); // _determineColumnIndexes // getNumberOfRows (points) @@ -3576,16 +3573,14 @@ return /******/ (function(modules) { // webpackBootstrap // getColumnRange // determine the location of x,y,z,value,filter columns - this.colX = "x"; - this.colY = "y"; - this.colZ = "z"; - this.colValue = "style"; - this.colFilter = "filter"; - - + this.colX = 'x'; + this.colY = 'y'; + this.colZ = 'z'; + this.colValue = 'style'; + this.colFilter = 'filter'; // check if a filter column is provided - if (data[0].hasOwnProperty("filter")) { + if (data[0].hasOwnProperty('filter')) { if (this.dataFilter === undefined) { this.dataFilter = new Filter(rawData, this.colFilter, this); this.dataFilter.setOnLoadCallback(function () { @@ -3594,7 +3589,6 @@ return /******/ (function(modules) { // webpackBootstrap } } - var withBars = this.style == Graph3d.STYLE.BAR || this.style == Graph3d.STYLE.BARCOLOR || this.style == Graph3d.STYLE.BARSIZE; // determine barWidth from data @@ -3652,8 +3646,6 @@ return /******/ (function(modules) { // webpackBootstrap this._setScale(); }; - - /** * Filter the data based on the current filter * @param {Array} data @@ -3684,7 +3676,7 @@ return /******/ (function(modules) { // webpackBootstrap } } - var sortNumber = function (a, b) { + var sortNumber = function sortNumber(a, b) { return a - b; }; dataX.sort(sortNumber); @@ -3768,58 +3760,57 @@ return /******/ (function(modules) { // webpackBootstrap this.containerElement.removeChild(this.containerElement.firstChild); } - this.frame = document.createElement("div"); - this.frame.style.position = "relative"; - this.frame.style.overflow = "hidden"; + this.frame = document.createElement('div'); + this.frame.style.position = 'relative'; + this.frame.style.overflow = 'hidden'; // create the graph canvas (HTML canvas element) - this.frame.canvas = document.createElement("canvas"); - this.frame.canvas.style.position = "relative"; + this.frame.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"; + var noCanvas = document.createElement('DIV'); + noCanvas.style.color = 'red'; + noCanvas.style.fontWeight = 'bold'; + noCanvas.style.padding = '10px'; + noCanvas.innerHTML = 'Error: your browser does not support HTML canvas'; this.frame.canvas.appendChild(noCanvas); } - this.frame.filter = document.createElement("div"); - this.frame.filter.style.position = "absolute"; - this.frame.filter.style.bottom = "0px"; - this.frame.filter.style.left = "0px"; - this.frame.filter.style.width = "100%"; + this.frame.filter = document.createElement('div'); + this.frame.filter.style.position = 'absolute'; + this.frame.filter.style.bottom = '0px'; + this.frame.filter.style.left = '0px'; + this.frame.filter.style.width = '100%'; this.frame.appendChild(this.frame.filter); // add event listeners to handle moving and zooming the contents var me = this; - var onmousedown = function (event) { + var onmousedown = function onmousedown(event) { me._onMouseDown(event); }; - var ontouchstart = function (event) { + var ontouchstart = function ontouchstart(event) { me._onTouchStart(event); }; - var onmousewheel = function (event) { + var onmousewheel = function onmousewheel(event) { me._onWheel(event); }; - var ontooltip = function (event) { + var ontooltip = function ontooltip(event) { me._onTooltip(event); }; // TODO: these events are never cleaned up... can give a 'memory leakage' - util.addEventListener(this.frame.canvas, "keydown", onkeydown); - util.addEventListener(this.frame.canvas, "mousedown", onmousedown); - util.addEventListener(this.frame.canvas, "touchstart", ontouchstart); - util.addEventListener(this.frame.canvas, "mousewheel", onmousewheel); - util.addEventListener(this.frame.canvas, "mousemove", ontooltip); + util.addEventListener(this.frame.canvas, 'keydown', onkeydown); + util.addEventListener(this.frame.canvas, 'mousedown', onmousedown); + util.addEventListener(this.frame.canvas, 'touchstart', ontouchstart); + util.addEventListener(this.frame.canvas, 'mousewheel', onmousewheel); + util.addEventListener(this.frame.canvas, 'mousemove', ontooltip); // add the new graph to the container element this.containerElement.appendChild(this.frame); }; - /** * Set a new size for the graph * @param {string} width Width in pixels or percentage (for example '800px' @@ -3838,26 +3829,25 @@ return /******/ (function(modules) { // webpackBootstrap * 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.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"; + this.frame.filter.style.width = this.frame.canvas.clientWidth - 2 * 10 + 'px'; }; /** * Start animation */ Graph3d.prototype.animationStart = function () { - if (!this.frame.filter || !this.frame.filter.slider) throw "No animation available"; + if (!this.frame.filter || !this.frame.filter.slider) throw 'No animation available'; this.frame.filter.slider.play(); }; - /** * Stop animation */ @@ -3867,7 +3857,6 @@ return /******/ (function(modules) { // webpackBootstrap this.frame.filter.slider.stop(); }; - /** * Resize the center position based on the current values in this.defaultXCenter * and this.defaultYCenter (which are strings with a percentage or a value @@ -3876,14 +3865,14 @@ return /******/ (function(modules) { // webpackBootstrap */ Graph3d.prototype._resizeCenter = function () { // calculate the horizontal center position - if (this.defaultXCenter.charAt(this.defaultXCenter.length - 1) === "%") { + if (this.defaultXCenter.charAt(this.defaultXCenter.length - 1) === '%') { this.xcenter = parseFloat(this.defaultXCenter) / 100 * this.frame.canvas.clientWidth; } else { this.xcenter = parseFloat(this.defaultXCenter); // supposed to be in px } // calculate the vertical center position - if (this.defaultYCenter.charAt(this.defaultYCenter.length - 1) === "%") { + 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 @@ -3922,7 +3911,6 @@ return /******/ (function(modules) { // webpackBootstrap this.redraw(); }; - /** * Retrieve the current camera rotation * @return {object} An object with parameters horizontal, vertical, and @@ -3941,7 +3929,6 @@ return /******/ (function(modules) { // webpackBootstrap // read the data this._dataInitialize(data, this.style); - if (this.dataFilter) { // apply filtering this.dataPoints = this.dataFilter._getDataPoints(); @@ -4059,7 +4046,7 @@ return /******/ (function(modules) { // webpackBootstrap */ Graph3d.prototype.redraw = function () { if (this.dataPoints === undefined) { - throw "Error: graph data not initialized"; + throw 'Error: graph data not initialized'; } this._resizeCanvas(); @@ -4088,12 +4075,11 @@ return /******/ (function(modules) { // webpackBootstrap */ Graph3d.prototype._redrawClear = function () { var canvas = this.frame.canvas; - var ctx = canvas.getContext("2d"); + var ctx = canvas.getContext('2d'); ctx.clearRect(0, 0, canvas.width, canvas.height); }; - /** * Redraw the legend showing the colors */ @@ -4101,6 +4087,7 @@ return /******/ (function(modules) { // webpackBootstrap var y; if (this.style === Graph3d.STYLE.DOTCOLOR || this.style === Graph3d.STYLE.DOTSIZE) { + var dotSize = this.frame.clientWidth * 0.02; var widthMin, widthMax; @@ -4120,9 +4107,9 @@ return /******/ (function(modules) { // webpackBootstrap } var canvas = this.frame.canvas; - var ctx = canvas.getContext("2d"); + var ctx = canvas.getContext('2d'); ctx.lineWidth = 1; - ctx.font = "14px arial"; // TODO: put in options + ctx.font = '14px arial'; // TODO: put in options if (this.style === Graph3d.STYLE.DOTCOLOR) { // draw the color bar @@ -4176,16 +4163,16 @@ return /******/ (function(modules) { // webpackBootstrap ctx.lineTo(left, y); ctx.stroke(); - ctx.textAlign = "right"; - ctx.textBaseline = "middle"; + ctx.textAlign = 'right'; + ctx.textBaseline = 'middle'; ctx.fillStyle = this.colorAxis; ctx.fillText(step.getCurrent(), left - 2 * gridLineLen, y); step.next(); } - ctx.textAlign = "right"; - ctx.textBaseline = "top"; + ctx.textAlign = 'right'; + ctx.textBaseline = 'top'; var label = this.legendLabel; ctx.fillText(label, right, bottom + this.margin); } @@ -4195,7 +4182,7 @@ return /******/ (function(modules) { // webpackBootstrap * Redraw the filter */ Graph3d.prototype._redrawFilter = function () { - this.frame.filter.innerHTML = ""; + this.frame.filter.innerHTML = ''; if (this.dataFilter) { var options = { @@ -4205,7 +4192,7 @@ return /******/ (function(modules) { // webpackBootstrap this.frame.filter.slider = slider; // TODO: css here is not nice here... - this.frame.filter.style.padding = "10px"; + this.frame.filter.style.padding = '10px'; //this.frame.filter.style.backgroundColor = '#EFEFEF'; slider.setValues(this.dataFilter.values); @@ -4213,7 +4200,7 @@ return /******/ (function(modules) { // webpackBootstrap // create an event handler var me = this; - var onchange = function () { + var onchange = function onchange() { var index = slider.getIndex(); me.dataFilter.selectValue(index); @@ -4236,34 +4223,32 @@ return /******/ (function(modules) { // webpackBootstrap } }; - /** * Redraw common information */ Graph3d.prototype._redrawInfo = function () { if (this.dataFilter) { var canvas = this.frame.canvas; - var ctx = canvas.getContext("2d"); + 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"; + ctx.font = '14px arial'; // TODO: put in options + ctx.lineStyle = 'gray'; + ctx.fillStyle = 'gray'; + ctx.textAlign = 'left'; + ctx.textBaseline = 'top'; var x = this.margin; var y = this.margin; - ctx.fillText(this.dataFilter.getLabel() + ": " + this.dataFilter.getSelectedValue(), x, y); + ctx.fillText(this.dataFilter.getLabel() + ': ' + this.dataFilter.getSelectedValue(), x, y); } }; - /** * Redraw the axis */ Graph3d.prototype._redrawAxis = function () { var canvas = this.frame.canvas, - ctx = canvas.getContext("2d"), + ctx = canvas.getContext('2d'), from, to, step, @@ -4280,7 +4265,7 @@ return /******/ (function(modules) { // webpackBootstrap // TODO: get the actual rendered style of the containerElement //ctx.font = this.containerElement.style.font; - ctx.font = 24 / this.camera.getArmLength() + "px arial"; + ctx.font = 24 / this.camera.getArmLength() + 'px arial'; // calculate the length for the short grid lines var gridLenX = 0.025 / this.scale.x; @@ -4328,18 +4313,18 @@ return /******/ (function(modules) { // webpackBootstrap 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"; + ctx.textAlign = 'center'; + ctx.textBaseline = 'top'; text.y += textMargin; } else if (Math.sin(armAngle * 2) < 0) { - ctx.textAlign = "right"; - ctx.textBaseline = "middle"; + ctx.textAlign = 'right'; + ctx.textBaseline = 'middle'; } else { - ctx.textAlign = "left"; - ctx.textBaseline = "middle"; + ctx.textAlign = 'left'; + ctx.textBaseline = 'middle'; } ctx.fillStyle = this.colorAxis; - ctx.fillText(" " + this.xValueLabel(step.getCurrent()) + " ", text.x, text.y); + ctx.fillText(' ' + this.xValueLabel(step.getCurrent()) + ' ', text.x, text.y); step.next(); } @@ -4382,18 +4367,18 @@ return /******/ (function(modules) { // webpackBootstrap 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"; + ctx.textAlign = 'center'; + ctx.textBaseline = 'top'; text.y += textMargin; } else if (Math.sin(armAngle * 2) > 0) { - ctx.textAlign = "right"; - ctx.textBaseline = "middle"; + ctx.textAlign = 'right'; + ctx.textBaseline = 'middle'; } else { - ctx.textAlign = "left"; - ctx.textBaseline = "middle"; + ctx.textAlign = 'left'; + ctx.textBaseline = 'middle'; } ctx.fillStyle = this.colorAxis; - ctx.fillText(" " + this.yValueLabel(step.getCurrent()) + " ", text.x, text.y); + ctx.fillText(' ' + this.yValueLabel(step.getCurrent()) + ' ', text.x, text.y); step.next(); } @@ -4417,10 +4402,10 @@ return /******/ (function(modules) { // webpackBootstrap ctx.lineTo(from.x - textMargin, from.y); ctx.stroke(); - ctx.textAlign = "right"; - ctx.textBaseline = "middle"; + ctx.textAlign = 'right'; + ctx.textBaseline = 'middle'; ctx.fillStyle = this.colorAxis; - ctx.fillText(this.zValueLabel(step.getCurrent()) + " ", from.x - 5, from.y); + ctx.fillText(this.zValueLabel(step.getCurrent()) + ' ', from.x - 5, from.y); step.next(); } @@ -4479,14 +4464,14 @@ return /******/ (function(modules) { // webpackBootstrap 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"; + ctx.textAlign = 'center'; + ctx.textBaseline = 'top'; } else if (Math.sin(armAngle * 2) < 0) { - ctx.textAlign = "right"; - ctx.textBaseline = "middle"; + ctx.textAlign = 'right'; + ctx.textBaseline = 'middle'; } else { - ctx.textAlign = "left"; - ctx.textBaseline = "middle"; + ctx.textAlign = 'left'; + ctx.textBaseline = 'middle'; } ctx.fillStyle = this.colorAxis; ctx.fillText(xLabel, text.x, text.y); @@ -4500,14 +4485,14 @@ return /******/ (function(modules) { // webpackBootstrap 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"; + ctx.textAlign = 'center'; + ctx.textBaseline = 'top'; } else if (Math.sin(armAngle * 2) > 0) { - ctx.textAlign = "right"; - ctx.textBaseline = "middle"; + ctx.textAlign = 'right'; + ctx.textBaseline = 'middle'; } else { - ctx.textAlign = "left"; - ctx.textBaseline = "middle"; + ctx.textAlign = 'left'; + ctx.textBaseline = 'middle'; } ctx.fillStyle = this.colorAxis; ctx.fillText(yLabel, text.x, text.y); @@ -4521,8 +4506,8 @@ return /******/ (function(modules) { // webpackBootstrap 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.textAlign = 'right'; + ctx.textBaseline = 'middle'; ctx.fillStyle = this.colorAxis; ctx.fillText(zLabel, text.x - offset, text.y); } @@ -4559,17 +4544,16 @@ return /******/ (function(modules) { // webpackBootstrap R = 0;G = 0;B = 0;break; } - return "RGB(" + parseInt(R * 255) + "," + parseInt(G * 255) + "," + parseInt(B * 255) + ")"; + return 'RGB(' + parseInt(R * 255) + ',' + parseInt(G * 255) + ',' + parseInt(B * 255) + ')'; }; - /** * 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"), + ctx = canvas.getContext('2d'), point, right, top, @@ -4584,7 +4568,6 @@ return /******/ (function(modules) { // webpackBootstrap v, zAvg; - if (this.dataPoints === undefined || this.dataPoints.length <= 0) return; // TODO: throw exception? // calculate the translations and screen position of all points @@ -4601,7 +4584,7 @@ return /******/ (function(modules) { // webpackBootstrap } // sort the points on depth of their (x,y) position (not on z) - var sortDepth = function (a, b) { + var sortDepth = function sortDepth(a, b) { return b.dist - a.dist; }; this.dataPoints.sort(sortDepth); @@ -4614,6 +4597,7 @@ return /******/ (function(modules) { // webpackBootstrap 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 @@ -4646,7 +4630,7 @@ return /******/ (function(modules) { // webpackBootstrap strokeStyle = this.colorAxis; } } else { - fillStyle = "gray"; + fillStyle = 'gray'; strokeStyle = this.colorAxis; } lineWidth = 0.5; @@ -4708,14 +4692,13 @@ return /******/ (function(modules) { // webpackBootstrap } }; - /** * 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 ctx = canvas.getContext('2d'); var i; if (this.dataPoints === undefined || this.dataPoints.length <= 0) return; // TODO: throw exception? @@ -4733,7 +4716,7 @@ return /******/ (function(modules) { // webpackBootstrap } // order the translated points by depth - var sortDepth = function (a, b) { + var sortDepth = function sortDepth(a, b) { return b.dist - a.dist; }; this.dataPoints.sort(sortDepth); @@ -4806,7 +4789,7 @@ return /******/ (function(modules) { // webpackBootstrap */ Graph3d.prototype._redrawDataBar = function () { var canvas = this.frame.canvas; - var ctx = canvas.getContext("2d"); + var ctx = canvas.getContext('2d'); var i, j, surface, corners; if (this.dataPoints === undefined || this.dataPoints.length <= 0) return; // TODO: throw exception? @@ -4824,7 +4807,7 @@ return /******/ (function(modules) { // webpackBootstrap } // order the translated points by depth - var sortDepth = function (a, b) { + var sortDepth = function sortDepth(a, b) { return b.dist - a.dist; }; this.dataPoints.sort(sortDepth); @@ -4919,14 +4902,13 @@ return /******/ (function(modules) { // webpackBootstrap } }; - /** * 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"), + ctx = canvas.getContext('2d'), point, i; @@ -4946,7 +4928,7 @@ return /******/ (function(modules) { // webpackBootstrap point = this.dataPoints[0]; ctx.lineWidth = 1; // TODO: make customizable - ctx.strokeStyle = "blue"; // TODO: make customizable + ctx.strokeStyle = 'blue'; // TODO: make customizable ctx.beginPath(); ctx.moveTo(point.screen.x, point.screen.y); } @@ -4989,7 +4971,7 @@ return /******/ (function(modules) { // webpackBootstrap this.startEnd = new Date(this.end); this.startArmRotation = this.camera.getArmRotation(); - this.frame.style.cursor = "move"; + 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 @@ -5001,12 +4983,11 @@ return /******/ (function(modules) { // webpackBootstrap this.onmouseup = function (event) { me._onMouseUp(event); }; - util.addEventListener(document, "mousemove", me.onmousemove); - util.addEventListener(document, "mouseup", me.onmouseup); + util.addEventListener(document, 'mousemove', me.onmousemove); + util.addEventListener(document, 'mouseup', me.onmouseup); util.preventDefault(event); }; - /** * Perform moving operating. * This function activated from within the funcion Graph.mouseDown(). @@ -5047,24 +5028,23 @@ return /******/ (function(modules) { // webpackBootstrap // fire a cameraPositionChange event var parameters = this.getCameraPosition(); - this.emit("cameraPositionChange", parameters); + this.emit('cameraPositionChange', parameters); util.preventDefault(event); }; - /** * Stop moving operating. * This function activated from within the funcion Graph.mouseDown(). * @param {event} event The event */ Graph3d.prototype._onMouseUp = function (event) { - this.frame.style.cursor = "auto"; + 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.removeEventListener(document, 'mousemove', this.onmousemove); + util.removeEventListener(document, 'mouseup', this.onmouseup); util.preventDefault(event); }; @@ -5131,8 +5111,8 @@ return /******/ (function(modules) { // webpackBootstrap this.ontouchend = function (event) { me._onTouchEnd(event); }; - util.addEventListener(document, "touchmove", me.ontouchmove); - util.addEventListener(document, "touchend", me.ontouchend); + util.addEventListener(document, 'touchmove', me.ontouchmove); + util.addEventListener(document, 'touchend', me.ontouchend); this._onMouseDown(event); }; @@ -5150,13 +5130,12 @@ return /******/ (function(modules) { // webpackBootstrap Graph3d.prototype._onTouchEnd = function (event) { this.touchDown = false; - util.removeEventListener(document, "touchmove", this.ontouchmove); - util.removeEventListener(document, "touchend", this.ontouchend); + 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/ @@ -5193,7 +5172,7 @@ return /******/ (function(modules) { // webpackBootstrap // fire a cameraPositionChange event var parameters = this.getCameraPosition(); - this.emit("cameraPositionChange", parameters); + this.emit('cameraPositionChange', parameters); // Prevent default actions caused by mouse wheel. // That might be ugly, but we handle scrolls somehow @@ -5278,7 +5257,6 @@ return /******/ (function(modules) { // webpackBootstrap } } - return closestDataPoint; }; @@ -5291,27 +5269,27 @@ return /******/ (function(modules) { // webpackBootstrap 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"; + 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, @@ -5330,14 +5308,14 @@ return /******/ (function(modules) { // webpackBootstrap this._hideTooltip(); this.tooltip.dataPoint = dataPoint; - if (typeof this.showTooltip === "function") { + 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.innerHTML = '' + '' + '' + '' + '
x:' + dataPoint.point.x + '
y:' + dataPoint.point.y + '
z:' + dataPoint.point.z + '
'; } - content.style.left = "0"; - content.style.top = "0"; + content.style.left = '0'; + content.style.top = '0'; this.frame.appendChild(content); this.frame.appendChild(line); this.frame.appendChild(dot); @@ -5352,12 +5330,12 @@ return /******/ (function(modules) { // webpackBootstrap 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"; + 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'; }; /** @@ -5381,14 +5359,13 @@ return /******/ (function(modules) { // webpackBootstrap /**--------------------------------------------------------------------------**/ - /** * Get the horizontal mouse position from a mouse event * @param {Event} event * @return {Number} mouse x */ function getMouseX(event) { - if ("clientX" in event) { + if ('clientX' in event) { return event.clientX; }return event.targetTouches[0] && event.targetTouches[0].clientX || 0; } @@ -5399,19 +5376,20 @@ return /******/ (function(modules) { // webpackBootstrap * @return {Number} mouse y */ function getMouseY(event) { - if ("clientY" in event) { + if ('clientY' in event) { return event.clientY; }return event.targetTouches[0] && event.targetTouches[0].clientY || 0; } module.exports = Graph3d; + // use use defaults /***/ }, /* 7 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; var Point3d = __webpack_require__(10); @@ -5552,7 +5530,7 @@ return /******/ (function(modules) { // webpackBootstrap /* 8 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; var DataView = __webpack_require__(4); @@ -5597,7 +5575,6 @@ return /******/ (function(modules) { // webpackBootstrap } }; - /** * Return the label * @return {string} label @@ -5606,7 +5583,6 @@ return /******/ (function(modules) { // webpackBootstrap return this.loaded; }; - /** * Return the loaded progress * @return {Number} percentage between 0 and 100 @@ -5622,7 +5598,6 @@ return /******/ (function(modules) { // webpackBootstrap return Math.round(i / len * 100); }; - /** * Return the label * @return {string} label @@ -5631,7 +5606,6 @@ return /******/ (function(modules) { // webpackBootstrap return this.graph.filterLabel; }; - /** * Return the columnIndex of the filter * @return {Number} columnIndex @@ -5664,12 +5638,11 @@ return /******/ (function(modules) { // webpackBootstrap * @return {*} value */ Filter.prototype.getValue = function (index) { - if (index >= this.values.length) throw "Error: index out of range"; + if (index >= this.values.length) throw 'Error: index out of range'; return this.values[index]; }; - /** * Retrieve the (filtered) dataPoints for the currently selected filter index * @param {Number} [index] (optional) @@ -5688,7 +5661,7 @@ return /******/ (function(modules) { // webpackBootstrap f.column = this.column; f.value = this.values[index]; - var dataView = new DataView(this.data, { filter: function (item) { + var dataView = new DataView(this.data, { filter: function filter(item) { return item[f.column] == f.value; } }).get(); dataPoints = this.graph._getDataPoints(dataView); @@ -5699,8 +5672,6 @@ return /******/ (function(modules) { // webpackBootstrap return dataPoints; }; - - /** * Set a callback function when the filter is fully loaded. */ @@ -5708,14 +5679,13 @@ return /******/ (function(modules) { // webpackBootstrap this.onLoadCallback = callback; }; - /** * Add a value to the list with available values for this filter * No double entries will be created. * @param {Number} index */ Filter.prototype.selectValue = function (index) { - if (index >= this.values.length) throw "Error: index out of range"; + if (index >= this.values.length) throw 'Error: index out of range'; this.index = index; this.value = this.values[index]; @@ -5736,16 +5706,16 @@ return /******/ (function(modules) { // webpackBootstrap // create a progress box if (frame.progress === undefined) { - frame.progress = document.createElement("DIV"); - frame.progress.style.position = "absolute"; - frame.progress.style.color = "gray"; + 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 + "%"; + 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"; + frame.progress.style.bottom = 60 + 'px'; // TODO: use height of slider + frame.progress.style.left = 10 + 'px'; var me = this; setTimeout(function () { @@ -5771,13 +5741,13 @@ return /******/ (function(modules) { // webpackBootstrap /* 9 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; - /** * @prototype Point2d * @param {Number} [x] * @param {Number} [y] */ + "use strict"; + function Point2d(x, y) { this.x = x !== undefined ? x : 0; this.y = y !== undefined ? y : 0; @@ -5789,14 +5759,14 @@ return /******/ (function(modules) { // webpackBootstrap /* 10 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; - /** * @prototype Point3d * @param {Number} [x] * @param {Number} [y] * @param {Number} [z] */ + "use strict"; + function Point3d(x, y, z) { this.x = x !== undefined ? x : 0; this.y = y !== undefined ? y : 0; @@ -5858,7 +5828,6 @@ return /******/ (function(modules) { // webpackBootstrap return crossproduct; }; - /** * Rtrieve the length of the vector (or the distance from this point to the origin * @return {Number} length @@ -5873,7 +5842,7 @@ return /******/ (function(modules) { // webpackBootstrap /* 11 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; var util = __webpack_require__(1); @@ -5888,51 +5857,51 @@ return /******/ (function(modules) { // webpackBootstrap */ function Slider(container, options) { if (container === undefined) { - throw "Error: No container element defined"; + 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 = document.createElement('DIV'); //this.frame.style.backgroundColor = '#E5E5E5'; - this.frame.style.width = "100%"; - this.frame.style.position = "relative"; + 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.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.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.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.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.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 @@ -6034,7 +6003,7 @@ return /******/ (function(modules) { // webpackBootstrap this.playNext(); if (this.frame) { - this.frame.play.value = "Stop"; + this.frame.play.value = 'Stop'; } }; @@ -6046,7 +6015,7 @@ return /******/ (function(modules) { // webpackBootstrap this.playTimeout = undefined; if (this.frame) { - this.frame.play.value = "Play"; + this.frame.play.value = 'Play'; } }; @@ -6084,7 +6053,6 @@ return /******/ (function(modules) { // webpackBootstrap this.playLoop = doLoop; }; - /** * Execute the onchange callback function */ @@ -6100,16 +6068,15 @@ return /******/ (function(modules) { // webpackBootstrap Slider.prototype.redraw = function () { if (this.frame) { // resize the bar - this.frame.bar.style.top = this.frame.clientHeight / 2 - this.frame.bar.offsetHeight / 2 + "px"; - this.frame.bar.style.width = this.frame.clientWidth - this.frame.prev.clientWidth - this.frame.play.clientWidth - this.frame.next.clientWidth - 30 + "px"; + this.frame.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'; // position the slider button var left = this.indexToLeft(this.index); - this.frame.slide.style.left = left + "px"; + this.frame.slide.style.left = left + 'px'; } }; - /** * Set the list with values for the slider * @param {Array} values A javascript array with values (any type) @@ -6131,7 +6098,7 @@ return /******/ (function(modules) { // webpackBootstrap this.redraw(); this.onChange(); } else { - throw "Error: index out of range"; + throw 'Error: index out of range'; } }; @@ -6143,7 +6110,6 @@ return /******/ (function(modules) { // webpackBootstrap return this.index; }; - /** * retrieve the currently selected value * @return {*} value @@ -6152,7 +6118,6 @@ return /******/ (function(modules) { // webpackBootstrap return this.values[this.index]; }; - Slider.prototype._onMouseDown = function (event) { // only react on left mouse button down var leftButtonDown = event.which ? event.which === 1 : event.button === 1; @@ -6161,7 +6126,7 @@ return /******/ (function(modules) { // webpackBootstrap this.startClientX = event.clientX; this.startSlideX = parseFloat(this.frame.slide.style.left); - this.frame.style.cursor = "move"; + 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 @@ -6173,12 +6138,11 @@ return /******/ (function(modules) { // webpackBootstrap this.onmouseup = function (event) { me._onMouseUp(event); }; - util.addEventListener(document, "mousemove", this.onmousemove); - util.addEventListener(document, "mouseup", this.onmouseup); + util.addEventListener(document, 'mousemove', this.onmousemove); + util.addEventListener(document, 'mouseup', this.onmouseup); util.preventDefault(event); }; - Slider.prototype.leftToIndex = function (left) { var width = parseFloat(this.frame.bar.style.width) - this.frame.slide.clientWidth - 10; var x = left - 3; @@ -6199,8 +6163,6 @@ return /******/ (function(modules) { // webpackBootstrap return left; }; - - Slider.prototype._onMouseMove = function (event) { var diff = event.clientX - this.startClientX; var x = this.startSlideX + diff; @@ -6212,13 +6174,12 @@ return /******/ (function(modules) { // webpackBootstrap util.preventDefault(); }; - Slider.prototype._onMouseUp = function (event) { - this.frame.style.cursor = "auto"; + this.frame.style.cursor = 'auto'; // remove event listeners - util.removeEventListener(document, "mousemove", this.onmousemove); - util.removeEventListener(document, "mouseup", this.onmouseup); + util.removeEventListener(document, 'mousemove', this.onmousemove); + util.removeEventListener(document, 'mouseup', this.onmouseup); util.preventDefault(); }; @@ -6229,8 +6190,6 @@ return /******/ (function(modules) { // webpackBootstrap /* 12 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; - /** * @prototype StepNumber * The class StepNumber is an iterator for Numbers. You provide a start and end @@ -6256,6 +6215,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param {boolean} prettyStep Optional. If true, the step size is rounded * To a pretty step size (like 1, 2, 5, 10, 20, 50, ...) */ + "use strict"; + function StepNumber(start, end, step, prettyStep) { // set default values this._start = 0; @@ -6306,7 +6267,7 @@ return /******/ (function(modules) { // webpackBootstrap * @return {Number} Nice step size */ StepNumber.calculatePrettyStep = function (step) { - var log10 = function (x) { + var log10 = function log10(x) { return Math.log(x) / Math.LN10; }; @@ -6373,7 +6334,7 @@ return /******/ (function(modules) { // webpackBootstrap /* 13 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; var Emitter = __webpack_require__(42); var Hammer = __webpack_require__(41); @@ -6398,7 +6359,7 @@ return /******/ (function(modules) { // webpackBootstrap */ function Timeline(container, items, groups, options) { if (!(this instanceof Timeline)) { - throw new SyntaxError("Constructor must be called with the new operator"); + throw new SyntaxError('Constructor must be called with the new operator'); } // if the third element is options, the forth is groups (optionally); @@ -6415,7 +6376,7 @@ return /******/ (function(modules) { // webpackBootstrap autoResize: true, - orientation: "bottom", + orientation: 'bottom', width: null, height: null, maxHeight: null, @@ -6439,10 +6400,10 @@ return /******/ (function(modules) { // webpackBootstrap }, hiddenDates: [], util: { - getScale: function () { + getScale: function getScale() { return me.timeAxis.step.scale; }, - getStep: function () { + getStep: function getStep() { return me.timeAxis.step.step; }, @@ -6526,8 +6487,8 @@ return /******/ (function(modules) { // webpackBootstrap // turn an array into a dataset newDataSet = new DataSet(items, { type: { - start: "Date", - end: "Date" + start: 'Date', + end: 'Date' } }); } @@ -6624,8 +6585,8 @@ return /******/ (function(modules) { // webpackBootstrap // get the specified item(s) var itemsData = this.itemsData.getDataSet().get(ids, { type: { - start: "Date", - end: "Date" + start: 'Date', + end: 'Date' } }); @@ -6634,7 +6595,7 @@ return /******/ (function(modules) { // webpackBootstrap var end = null; itemsData.forEach(function (itemData) { var s = itemData.start.valueOf(); - var e = "end" in itemData ? itemData.end.valueOf() : itemData.start.valueOf(); + var e = 'end' in itemData ? itemData.end.valueOf() : itemData.start.valueOf(); if (start === null || s < start) { start = s; @@ -6669,22 +6630,22 @@ return /******/ (function(modules) { // webpackBootstrap if (dataset) { // calculate the minimum value of the field 'start' - var minItem = dataset.min("start"); - min = minItem ? util.convert(minItem.start, "Date").valueOf() : null; + 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"); + var maxStartItem = dataset.max('start'); if (maxStartItem) { - max = util.convert(maxStartItem.start, "Date").valueOf(); + max = util.convert(maxStartItem.start, 'Date').valueOf(); } - var maxEndItem = dataset.max("end"); + var maxEndItem = dataset.max('end'); if (maxEndItem) { if (max == null) { - max = util.convert(maxEndItem.end, "Date").valueOf(); + max = util.convert(maxEndItem.end, 'Date').valueOf(); } else { - max = Math.max(max, util.convert(maxEndItem.end, "Date").valueOf()); + max = Math.max(max, util.convert(maxEndItem.end, 'Date').valueOf()); } } } @@ -6695,14 +6656,13 @@ return /******/ (function(modules) { // webpackBootstrap }; }; - module.exports = Timeline; /***/ }, /* 14 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; var Emitter = __webpack_require__(42); var Hammer = __webpack_require__(41); @@ -6739,7 +6699,7 @@ return /******/ (function(modules) { // webpackBootstrap autoResize: true, - orientation: "bottom", + orientation: 'bottom', width: null, height: null, maxHeight: null, @@ -6834,8 +6794,8 @@ return /******/ (function(modules) { // webpackBootstrap // turn an array into a dataset newDataSet = new DataSet(items, { type: { - start: "Date", - end: "Date" + start: 'Date', + end: 'Date' } }); } @@ -6892,7 +6852,7 @@ return /******/ (function(modules) { // webpackBootstrap if (this.linegraph.groups[groupId] !== undefined) { return this.linegraph.groups[groupId].getLegend(width, height); } else { - return "cannot find group:" + groupId; + return 'cannot find group:' + groupId; } }; @@ -6909,7 +6869,6 @@ return /******/ (function(modules) { // webpackBootstrap } }; - /** * Get the data range of the item set. * @returns {{min: Date, max: Date}} range A range with a start and end Date. @@ -6926,7 +6885,7 @@ return /******/ (function(modules) { // webpackBootstrap 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(); + var value = util.convert(item.x, 'Date').valueOf(); min = min == null ? value : min > value ? value : min; max = max == null ? value : max < value ? value : max; } @@ -6940,8 +6899,6 @@ return /******/ (function(modules) { // webpackBootstrap }; }; - - module.exports = Graph2d; /***/ }, @@ -6952,7 +6909,6 @@ return /******/ (function(modules) { // webpackBootstrap var moment = __webpack_require__(40); - /** * used in Core to convert the options into a volatile variable * @@ -6977,7 +6933,6 @@ return /******/ (function(modules) { // webpackBootstrap } }; - /** * create new entrees for the repeating hidden dates * @param body @@ -7007,6 +6962,7 @@ return /******/ (function(modules) { // webpackBootstrap var duration = endDate - startDate; if (duration >= 4 * pixelTime) { + var offset = 0; var runUntil = end.clone(); switch (hiddenDates[i].repeat) { @@ -7123,7 +7079,6 @@ return /******/ (function(modules) { // webpackBootstrap } }; - /** * remove duplicates from the hidden dates list. Duplicates are evil. They mess everything up. * Scales with N^2 @@ -7204,7 +7159,6 @@ return /******/ (function(modules) { // webpackBootstrap } }; - ///** // * Used in TimeStep to avoid the hidden times. // * @param timeStep @@ -7253,7 +7207,6 @@ return /******/ (function(modules) { // webpackBootstrap } }; - /** * Replaces the core toTime methods * @param body @@ -7277,7 +7230,6 @@ return /******/ (function(modules) { // webpackBootstrap } }; - /** * Support function * @@ -7298,7 +7250,6 @@ return /******/ (function(modules) { // webpackBootstrap return duration; }; - /** * Support function * @param hiddenDates @@ -7360,8 +7311,6 @@ return /******/ (function(modules) { // webpackBootstrap return hiddenDuration; }; - - /** * used to step over to either side of a hidden block. Correction is disabled on tablets, might be set to true * @param hiddenDates @@ -7391,7 +7340,6 @@ return /******/ (function(modules) { // webpackBootstrap } }; - /** * Check if a time is hidden * @@ -7417,8 +7365,6 @@ return /******/ (function(modules) { // webpackBootstrap /* 16 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; - /** * @constructor DataStep * The class DataStep is an iterator for data for the lineGraph. You provide a start data point and an @@ -7445,6 +7391,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param {Date} [end] The end date * @param {Number} [minimumStep] Optional. Minimum step size in milliseconds */ + "use strict"; + function DataStep(start, end, minimumStep, containerHeight, customRange, alignZeros) { // variables this.current = 0; @@ -7466,8 +7414,6 @@ return /******/ (function(modules) { // webpackBootstrap this.setRange(start, end, minimumStep, containerHeight, customRange); } - - /** * Set a new range * If minimumStep is provided, the step size is chosen as close as possible @@ -7533,8 +7479,6 @@ return /******/ (function(modules) { // webpackBootstrap this.step = magnitudefactor * this.minorSteps[minorStepIdx]; }; - - /** * Round the current date to the first minor date value * This must be executed once when the current date is set to start Date @@ -7558,7 +7502,6 @@ return /******/ (function(modules) { // webpackBootstrap this.deadSpace = this.roundToMinor(niceEnd) - niceEnd + this.roundToMinor(niceStart) - niceStart; this.marginRange = this.marginEnd - this.marginStart; - this.current = this.marginEnd; }; @@ -7571,7 +7514,6 @@ return /******/ (function(modules) { // webpackBootstrap } }; - /** * Check if the there is a next step * @return {boolean} true if the current date has not passed the end date @@ -7602,8 +7544,6 @@ return /******/ (function(modules) { // webpackBootstrap this.marginRange = this.marginEnd - this.marginStart; }; - - /** * Get the current datetime * @return {String} current The current date @@ -7681,10 +7621,10 @@ return /******/ (function(modules) { // webpackBootstrap /* 17 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; var util = __webpack_require__(1); - var hammerUtil = __webpack_require__(64); + var hammerUtil = __webpack_require__(44); var moment = __webpack_require__(40); var Component = __webpack_require__(25); var DateUtil = __webpack_require__(15); @@ -7699,8 +7639,8 @@ return /******/ (function(modules) { // webpackBootstrap */ 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.start = now.clone().add(-3, 'days').valueOf(); // Number + this.end = now.clone().add(4, 'days').valueOf(); // Number this.body = body; this.deltaDifference = 0; @@ -7712,7 +7652,7 @@ return /******/ (function(modules) { // webpackBootstrap this.defaultOptions = { start: null, end: null, - direction: "horizontal", // 'horizontal' or 'vertical' + direction: 'horizontal', // 'horizontal' or 'vertical' moveable: true, zoomable: true, min: null, @@ -7728,19 +7668,19 @@ return /******/ (function(modules) { // webpackBootstrap this.animateTimer = null; // drag listeners for dragging - this.body.emitter.on("panstart", this._onDragStart.bind(this)); - this.body.emitter.on("panmove", this._onDrag.bind(this)); - this.body.emitter.on("panend", this._onDragEnd.bind(this)); + this.body.emitter.on('panstart', this._onDragStart.bind(this)); + this.body.emitter.on('panmove', this._onDrag.bind(this)); + this.body.emitter.on('panend', this._onDragEnd.bind(this)); // ignore dragging when holding - this.body.emitter.on("press", this._onHold.bind(this)); + this.body.emitter.on('press', this._onHold.bind(this)); // mouse wheel for zooming - this.body.emitter.on("mousewheel", this._onMouseWheel.bind(this)); + this.body.emitter.on('mousewheel', this._onMouseWheel.bind(this)); // pinch to zoom - this.body.emitter.on("touch", this._onTouch.bind(this)); - this.body.emitter.on("pinch", this._onPinch.bind(this)); + this.body.emitter.on('touch', this._onTouch.bind(this)); + this.body.emitter.on('pinch', this._onPinch.bind(this)); this.setOptions(options); } @@ -7766,10 +7706,10 @@ return /******/ (function(modules) { // webpackBootstrap Range.prototype.setOptions = function (options) { if (options) { // copy the options that we know - var fields = ["direction", "min", "max", "zoomMin", "zoomMax", "moveable", "zoomable", "activate", "hiddenDates"]; + var fields = ['direction', 'min', 'max', 'zoomMin', 'zoomMax', 'moveable', 'zoomable', 'activate', 'hiddenDates']; util.selectiveExtend(fields, this.options, options); - if ("start" in options || "end" in options) { + if ('start' in options || 'end' in options) { // apply a new range. both start and end are optional this.setRange(options.start, options.end); } @@ -7781,8 +7721,8 @@ return /******/ (function(modules) { // webpackBootstrap * @param {String} direction 'horizontal' or 'vertical' */ function validateDirection(direction) { - if (direction != "horizontal" && direction != "vertical") { - throw new TypeError("Unknown direction \"" + direction + "\". " + "Choose \"horizontal\" or \"vertical\"."); + if (direction != 'horizontal' && direction != 'vertical') { + throw new TypeError('Unknown direction "' + direction + '". ' + 'Choose "horizontal" or "vertical".'); } } @@ -7802,19 +7742,29 @@ return /******/ (function(modules) { // webpackBootstrap 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; + var _start = start != undefined ? util.convert(start, 'Date').valueOf() : null; + var _end = end != undefined ? util.convert(end, 'Date').valueOf() : null; this._cancelAnimation(); if (animate) { var me = this; var initStart = this.start; var initEnd = this.end; - var duration = typeof animate === "number" ? animate : 500; + var duration = typeof animate === 'number' ? animate : 500; var initTime = new Date().valueOf(); var anyChanged = false; - var next = function () { + var next = (function (_next) { + function next() { + return _next.apply(this, arguments); + } + + next.toString = function () { + return _next.toString(); + }; + + return next; + })(function () { if (!me.props.touch.dragging) { var now = new Date().valueOf(); var time = now - initTime; @@ -7826,12 +7776,12 @@ return /******/ (function(modules) { // webpackBootstrap 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 }); + me.body.emitter.emit('rangechange', { start: new Date(me.start), end: new Date(me.end), byUser: byUser }); } if (done) { if (anyChanged) { - me.body.emitter.emit("rangechanged", { start: new Date(me.start), end: new Date(me.end), byUser: byUser }); + 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 @@ -7839,7 +7789,7 @@ return /******/ (function(modules) { // webpackBootstrap me.animateTimer = setTimeout(next, 20); } } - }; + }); return next(); } else { @@ -7847,8 +7797,8 @@ return /******/ (function(modules) { // webpackBootstrap 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); + this.body.emitter.emit('rangechange', params); + this.body.emitter.emit('rangechanged', params); } } }; @@ -7874,18 +7824,18 @@ return /******/ (function(modules) { // webpackBootstrap * @private */ Range.prototype._applyRange = function (start, end) { - var newStart = start != null ? util.convert(start, "Date").valueOf() : this.start, - newEnd = end != null ? util.convert(end, "Date").valueOf() : this.end, - max = this.options.max != null ? util.convert(this.options.max, "Date").valueOf() : null, - min = this.options.min != null ? util.convert(this.options.min, "Date").valueOf() : null, + 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 + "\""); + throw new Error('Invalid start "' + start + '"'); } if (isNaN(newEnd) || newEnd === null) { - throw new Error("Invalid end \"" + end + "\""); + throw new Error('Invalid end "' + end + '"'); } // prevent start < end @@ -7970,7 +7920,7 @@ return /******/ (function(modules) { // webpackBootstrap // 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.body.emitter.emit('checkRangedItems'); } this.start = newStart; @@ -8044,7 +7994,7 @@ return /******/ (function(modules) { // webpackBootstrap this.props.touch.dragging = true; if (this.body.dom.root) { - this.body.dom.root.style.cursor = "move"; + this.body.dom.root.style.cursor = 'move'; } }; @@ -8064,7 +8014,7 @@ return /******/ (function(modules) { // webpackBootstrap var direction = this.options.direction; validateDirection(direction); - var delta = direction == "horizontal" ? event.deltaX : event.deltaY; + var delta = direction == 'horizontal' ? event.deltaX : event.deltaY; delta -= this.deltaDifference; var interval = this.props.touch.end - this.props.touch.start; @@ -8072,7 +8022,7 @@ return /******/ (function(modules) { // webpackBootstrap var duration = DateUtil.getHiddenDurationBetween(this.body.hiddenDates, this.start, this.end); interval -= duration; - var width = direction == "horizontal" ? this.body.domProps.center.width : this.body.domProps.center.height; + 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; @@ -8092,7 +8042,7 @@ return /******/ (function(modules) { // webpackBootstrap this._applyRange(newStart, newEnd); // fire a rangechange event - this.body.emitter.emit("rangechange", { + this.body.emitter.emit('rangechange', { start: new Date(this.start), end: new Date(this.end), byUser: true @@ -8115,11 +8065,11 @@ return /******/ (function(modules) { // webpackBootstrap this.props.touch.dragging = false; if (this.body.dom.root) { - this.body.dom.root.style.cursor = "auto"; + this.body.dom.root.style.cursor = 'auto'; } // fire a rangechanged event - this.body.emitter.emit("rangechanged", { + this.body.emitter.emit('rangechanged', { start: new Date(this.start), end: new Date(this.end), byUser: true @@ -8254,7 +8204,7 @@ return /******/ (function(modules) { // webpackBootstrap validateDirection(direction); - if (direction == "horizontal") { + if (direction == 'horizontal') { return this.body.util.toTime(pointer.x).valueOf(); } else { var height = this.body.domProps.center.height; @@ -8317,8 +8267,6 @@ return /******/ (function(modules) { // webpackBootstrap this.endToFront = true; // revert to default }; - - /** * 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 @@ -8361,9 +8309,9 @@ return /******/ (function(modules) { // webpackBootstrap /* 18 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; - // Utility functions for ordering and stacking of items + 'use strict'; + var EPSILON = 0.001; // used when checking collisions, to prevent round-off errors /** @@ -8383,8 +8331,8 @@ return /******/ (function(modules) { // webpackBootstrap */ 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; + var aTime = 'end' in a.data ? a.data.end : a.data.start, + bTime = 'end' in b.data ? b.data.end : b.data.start; return aTime - bTime; }); @@ -8439,7 +8387,6 @@ return /******/ (function(modules) { // webpackBootstrap } }; - /** * Adjust vertical positions of the items without stacking them * @param {Item[]} items @@ -8486,7 +8433,7 @@ return /******/ (function(modules) { // webpackBootstrap /* 19 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; var moment = __webpack_require__(40); var DateUtil = __webpack_require__(15); @@ -8525,7 +8472,7 @@ return /******/ (function(modules) { // webpackBootstrap this._end = new Date(); this.autoScale = true; - this.scale = "day"; + this.scale = 'day'; this.step = 1; // initialize the range @@ -8546,24 +8493,24 @@ return /******/ (function(modules) { // webpackBootstrap // Time formatting TimeStep.FORMAT = { minorLabels: { - millisecond: "SSS", - second: "s", - minute: "HH:mm", - hour: "HH:mm", - weekday: "ddd D", - day: "D", - month: "MMM", - year: "YYYY" + 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: "" + 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: '' } }; @@ -8590,7 +8537,7 @@ return /******/ (function(modules) { // webpackBootstrap */ TimeStep.prototype.setRange = function (start, end, minimumStep) { if (!(start instanceof Date) || !(end instanceof Date)) { - throw "No legal start or end date in method setRange"; + throw 'No legal start or end date in method setRange'; } this._start = start != undefined ? new Date(start.valueOf()) : new Date(); @@ -8618,20 +8565,19 @@ return /******/ (function(modules) { // webpackBootstrap // IMPORTANT: we have no breaks in this switch! (this is no bug) // noinspection FallThroughInSwitchStatementJS switch (this.scale) { - case "year": + case 'year': this.current.setFullYear(this.step * Math.floor(this.current.getFullYear() / this.step)); this.current.setMonth(0); - case "month": + case 'month': this.current.setDate(1); - case "day": - // intentional fall through - case "weekday": + case 'day': // intentional fall through + case 'weekday': this.current.setHours(0); - case "hour": + case 'hour': this.current.setMinutes(0); - case "minute": + case 'minute': this.current.setSeconds(0); - case "second": + case 'second': this.current.setMilliseconds(0); //case 'millisecond': // nothing to do for milliseconds } @@ -8639,21 +8585,20 @@ return /******/ (function(modules) { // webpackBootstrap 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": + case 'millisecond': this.current.setMilliseconds(this.current.getMilliseconds() - this.current.getMilliseconds() % this.step);break; - case "second": + case 'second': this.current.setSeconds(this.current.getSeconds() - this.current.getSeconds() % this.step);break; - case "minute": + case 'minute': this.current.setMinutes(this.current.getMinutes() - this.current.getMinutes() % this.step);break; - case "hour": + case 'hour': this.current.setHours(this.current.getHours() - this.current.getHours() % this.step);break; - case "weekday": - // intentional fall through - case "day": + case 'weekday': // intentional fall through + case 'day': this.current.setDate(this.current.getDate() - 1 - (this.current.getDate() - 1) % this.step + 1);break; - case "month": + case 'month': this.current.setMonth(this.current.getMonth() - this.current.getMonth() % this.step);break; - case "year": + case 'year': this.current.setFullYear(this.current.getFullYear() - this.current.getFullYear() % this.step);break; default: break; @@ -8679,48 +8624,45 @@ return /******/ (function(modules) { // webpackBootstrap // (end of March and end of October) if (this.current.getMonth() < 6) { switch (this.scale) { - case "millisecond": - + case 'millisecond': this.current = new Date(this.current.valueOf() + this.step);break; - case "second": + case 'second': this.current = new Date(this.current.valueOf() + this.step * 1000);break; - case "minute": + case 'minute': this.current = new Date(this.current.valueOf() + this.step * 1000 * 60);break; - case "hour": + 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": + case 'weekday': // intentional fall through + case 'day': this.current.setDate(this.current.getDate() + this.step);break; - case "month": + case 'month': this.current.setMonth(this.current.getMonth() + this.step);break; - case "year": + case 'year': this.current.setFullYear(this.current.getFullYear() + this.step);break; default: break; } } else { switch (this.scale) { - case "millisecond": + case 'millisecond': this.current = new Date(this.current.valueOf() + this.step);break; - case "second": + case 'second': this.current.setSeconds(this.current.getSeconds() + this.step);break; - case "minute": + case 'minute': this.current.setMinutes(this.current.getMinutes() + this.step);break; - case "hour": + case 'hour': this.current.setHours(this.current.getHours() + this.step);break; - case "weekday": - // intentional fall through - case "day": + case 'weekday': // intentional fall through + case 'day': this.current.setDate(this.current.getDate() + this.step);break; - case "month": + case 'month': this.current.setMonth(this.current.getMonth() + this.step);break; - case "year": + case 'year': this.current.setFullYear(this.current.getFullYear() + this.step);break; default: break; @@ -8730,21 +8672,20 @@ return /******/ (function(modules) { // webpackBootstrap if (this.step != 1) { // round down to the correct major value switch (this.scale) { - case "millisecond": + case 'millisecond': if (this.current.getMilliseconds() < this.step) this.current.setMilliseconds(0);break; - case "second": + case 'second': if (this.current.getSeconds() < this.step) this.current.setSeconds(0);break; - case "minute": + case 'minute': if (this.current.getMinutes() < this.step) this.current.setMinutes(0);break; - case "hour": + case 'hour': if (this.current.getHours() < this.step) this.current.setHours(0);break; - case "weekday": - // intentional fall through - case "day": + case 'weekday': // intentional fall through + case 'day': if (this.current.getDate() < this.step + 1) this.current.setDate(1);break; - case "month": + case 'month': if (this.current.getMonth() < this.step) this.current.setMonth(0);break; - case "year": + case 'year': break; // nothing to do for year default: break; @@ -8759,7 +8700,6 @@ return /******/ (function(modules) { // webpackBootstrap DateUtil.stepOverHiddenDates(this, prev); }; - /** * Get the current datetime * @return {Date} current The current date @@ -8781,7 +8721,7 @@ return /******/ (function(modules) { // webpackBootstrap * Choose for example 1, 2, 5, or 10. */ TimeStep.prototype.setScale = function (params) { - if (params && typeof params.scale == "string") { + if (params && typeof params.scale == 'string') { this.scale = params.scale; this.step = params.step > 0 ? params.step : 1; this.autoScale = false; @@ -8796,7 +8736,6 @@ return /******/ (function(modules) { // webpackBootstrap this.autoScale = enable; }; - /** * Automatically determine the scale that bests fits the provided minimum step * @param {Number} [minimumStep] The minimum step size in milliseconds @@ -8818,91 +8757,91 @@ return /******/ (function(modules) { // webpackBootstrap // find the smallest step that is larger than the provided minimumStep if (stepYear * 1000 > minimumStep) { - this.scale = "year";this.step = 1000; + this.scale = 'year';this.step = 1000; } if (stepYear * 500 > minimumStep) { - this.scale = "year";this.step = 500; + this.scale = 'year';this.step = 500; } if (stepYear * 100 > minimumStep) { - this.scale = "year";this.step = 100; + this.scale = 'year';this.step = 100; } if (stepYear * 50 > minimumStep) { - this.scale = "year";this.step = 50; + this.scale = 'year';this.step = 50; } if (stepYear * 10 > minimumStep) { - this.scale = "year";this.step = 10; + this.scale = 'year';this.step = 10; } if (stepYear * 5 > minimumStep) { - this.scale = "year";this.step = 5; + this.scale = 'year';this.step = 5; } if (stepYear > minimumStep) { - this.scale = "year";this.step = 1; + this.scale = 'year';this.step = 1; } if (stepMonth * 3 > minimumStep) { - this.scale = "month";this.step = 3; + this.scale = 'month';this.step = 3; } if (stepMonth > minimumStep) { - this.scale = "month";this.step = 1; + this.scale = 'month';this.step = 1; } if (stepDay * 5 > minimumStep) { - this.scale = "day";this.step = 5; + this.scale = 'day';this.step = 5; } if (stepDay * 2 > minimumStep) { - this.scale = "day";this.step = 2; + this.scale = 'day';this.step = 2; } if (stepDay > minimumStep) { - this.scale = "day";this.step = 1; + this.scale = 'day';this.step = 1; } if (stepDay / 2 > minimumStep) { - this.scale = "weekday";this.step = 1; + this.scale = 'weekday';this.step = 1; } if (stepHour * 4 > minimumStep) { - this.scale = "hour";this.step = 4; + this.scale = 'hour';this.step = 4; } if (stepHour > minimumStep) { - this.scale = "hour";this.step = 1; + this.scale = 'hour';this.step = 1; } if (stepMinute * 15 > minimumStep) { - this.scale = "minute";this.step = 15; + this.scale = 'minute';this.step = 15; } if (stepMinute * 10 > minimumStep) { - this.scale = "minute";this.step = 10; + this.scale = 'minute';this.step = 10; } if (stepMinute * 5 > minimumStep) { - this.scale = "minute";this.step = 5; + this.scale = 'minute';this.step = 5; } if (stepMinute > minimumStep) { - this.scale = "minute";this.step = 1; + this.scale = 'minute';this.step = 1; } if (stepSecond * 15 > minimumStep) { - this.scale = "second";this.step = 15; + this.scale = 'second';this.step = 15; } if (stepSecond * 10 > minimumStep) { - this.scale = "second";this.step = 10; + this.scale = 'second';this.step = 10; } if (stepSecond * 5 > minimumStep) { - this.scale = "second";this.step = 5; + this.scale = 'second';this.step = 5; } if (stepSecond > minimumStep) { - this.scale = "second";this.step = 1; + this.scale = 'second';this.step = 1; } if (stepMillisecond * 200 > minimumStep) { - this.scale = "millisecond";this.step = 200; + this.scale = 'millisecond';this.step = 200; } if (stepMillisecond * 100 > minimumStep) { - this.scale = "millisecond";this.step = 100; + this.scale = 'millisecond';this.step = 100; } if (stepMillisecond * 50 > minimumStep) { - this.scale = "millisecond";this.step = 50; + this.scale = 'millisecond';this.step = 50; } if (stepMillisecond * 10 > minimumStep) { - this.scale = "millisecond";this.step = 10; + this.scale = 'millisecond';this.step = 10; } if (stepMillisecond * 5 > minimumStep) { - this.scale = "millisecond";this.step = 5; + this.scale = 'millisecond';this.step = 5; } if (stepMillisecond > minimumStep) { - this.scale = "millisecond";this.step = 1; + this.scale = 'millisecond';this.step = 1; } }; @@ -8919,7 +8858,7 @@ return /******/ (function(modules) { // webpackBootstrap TimeStep.snap = function (date, scale, step) { var clone = new Date(date.valueOf()); - if (scale == "year") { + if (scale == 'year') { var year = clone.getFullYear() + Math.round(clone.getMonth() / 12); clone.setFullYear(Math.round(year / step) * step); clone.setMonth(0); @@ -8928,7 +8867,7 @@ return /******/ (function(modules) { // webpackBootstrap clone.setMinutes(0); clone.setSeconds(0); clone.setMilliseconds(0); - } else if (scale == "month") { + } else if (scale == 'month') { if (clone.getDate() > 15) { clone.setDate(1); clone.setMonth(clone.getMonth() + 1); @@ -8941,7 +8880,7 @@ return /******/ (function(modules) { // webpackBootstrap clone.setMinutes(0); clone.setSeconds(0); clone.setMilliseconds(0); - } else if (scale == "day") { + } else if (scale == 'day') { //noinspection FallthroughInSwitchStatementJS switch (step) { case 5: @@ -8953,7 +8892,7 @@ return /******/ (function(modules) { // webpackBootstrap clone.setMinutes(0); clone.setSeconds(0); clone.setMilliseconds(0); - } else if (scale == "weekday") { + } else if (scale == 'weekday') { //noinspection FallthroughInSwitchStatementJS switch (step) { case 5: @@ -8965,7 +8904,7 @@ return /******/ (function(modules) { // webpackBootstrap clone.setMinutes(0); clone.setSeconds(0); clone.setMilliseconds(0); - } else if (scale == "hour") { + } else if (scale == 'hour') { switch (step) { case 4: clone.setMinutes(Math.round(clone.getMinutes() / 60) * 60);break; @@ -8974,7 +8913,7 @@ return /******/ (function(modules) { // webpackBootstrap } clone.setSeconds(0); clone.setMilliseconds(0); - } else if (scale == "minute") { + } else if (scale == 'minute') { //noinspection FallthroughInSwitchStatementJS switch (step) { case 15: @@ -8988,7 +8927,7 @@ return /******/ (function(modules) { // webpackBootstrap clone.setSeconds(Math.round(clone.getSeconds() / 30) * 30);break; } clone.setMilliseconds(0); - } else if (scale == "second") { + } else if (scale == 'second') { //noinspection FallthroughInSwitchStatementJS switch (step) { case 15: @@ -9001,7 +8940,7 @@ return /******/ (function(modules) { // webpackBootstrap default: clone.setMilliseconds(Math.round(clone.getMilliseconds() / 500) * 500);break; } - } else if (scale == "millisecond") { + } else if (scale == 'millisecond') { var _step = step > 5 ? step / 2 : 1; clone.setMilliseconds(Math.round(clone.getMilliseconds() / _step) * _step); } @@ -9018,14 +8957,14 @@ return /******/ (function(modules) { // webpackBootstrap 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": + case 'year': + case 'month': + case 'weekday': + case 'day': + case 'hour': + case 'minute': + case 'second': + case 'millisecond': return true; default: return false; @@ -9033,12 +8972,12 @@ return /******/ (function(modules) { // webpackBootstrap } else if (this.switchedMonth == true) { this.switchedMonth = false; switch (this.scale) { - case "weekday": - case "day": - case "hour": - case "minute": - case "second": - case "millisecond": + case 'weekday': + case 'day': + case 'hour': + case 'minute': + case 'second': + case 'millisecond': return true; default: return false; @@ -9046,10 +8985,10 @@ return /******/ (function(modules) { // webpackBootstrap } else if (this.switchedDay == true) { this.switchedDay = false; switch (this.scale) { - case "millisecond": - case "second": - case "minute": - case "hour": + case 'millisecond': + case 'second': + case 'minute': + case 'hour': return true; default: return false; @@ -9057,28 +8996,26 @@ return /******/ (function(modules) { // webpackBootstrap } switch (this.scale) { - case "millisecond": + case 'millisecond': return this.current.getMilliseconds() == 0; - case "second": + case 'second': return this.current.getSeconds() == 0; - case "minute": + case 'minute': return this.current.getHours() == 0 && this.current.getMinutes() == 0; - case "hour": + case 'hour': return this.current.getHours() == 0; - case "weekday": - // intentional fall through - case "day": + case 'weekday': // intentional fall through + case 'day': return this.current.getDate() == 1; - case "month": + case 'month': return this.current.getMonth() == 0; - case "year": + case 'year': return false; default: return false; } }; - /** * Returns formatted text for the minor axislabel, depending on the current * date and the scale. For example when scale is MINUTE, the current time is @@ -9091,7 +9028,7 @@ return /******/ (function(modules) { // webpackBootstrap } var format = this.format.minorLabels[this.scale]; - return format && format.length > 0 ? moment(date).format(format) : ""; + return format && format.length > 0 ? moment(date).format(format) : ''; }; /** @@ -9106,77 +9043,77 @@ return /******/ (function(modules) { // webpackBootstrap } var format = this.format.majorLabels[this.scale]; - return format && format.length > 0 ? moment(date).format(format) : ""; + return format && format.length > 0 ? moment(date).format(format) : ''; }; 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 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"; + return value / step % 2 == 0 ? ' even' : ' odd'; } function today(date) { - if (date.isSame(new Date(), "day")) { - return " today"; + 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 ' tomorrow'; } - if (date.isSame(moment().add(-1, "day"), "day")) { - return " yesterday"; + if (date.isSame(moment().add(-1, 'day'), 'day')) { + return ' yesterday'; } - return ""; + return ''; } function currentWeek(date) { - return date.isSame(new Date(), "week") ? " current-week" : ""; + return date.isSame(new Date(), 'week') ? ' current-week' : ''; } function currentMonth(date) { - return date.isSame(new Date(), "month") ? " current-month" : ""; + return date.isSame(new Date(), 'month') ? ' current-month' : ''; } function currentYear(date) { - return date.isSame(new Date(), "year") ? " current-year" : ""; + return date.isSame(new Date(), 'year') ? ' current-year' : ''; } switch (this.scale) { - case "millisecond": + case 'millisecond': return even(date.milliseconds()).trim(); - case "second": + case 'second': return even(date.seconds()).trim(); - case "minute": + case 'minute': return even(date.minutes()).trim(); - case "hour": + case 'hour': var hours = date.hours(); if (this.step == 4) { - hours = hours + "-h" + (hours + 4); + hours = hours + '-h' + (hours + 4); } - return "h" + hours + today(date) + even(date.hours()); + return 'h' + hours + today(date) + even(date.hours()); - case "weekday": - return date.format("dddd").toLowerCase() + today(date) + currentWeek(date) + even(date.date()); + case 'weekday': + return date.format('dddd').toLowerCase() + today(date) + currentWeek(date) + even(date.date()); - case "day": + case 'day': var day = date.date(); - var month = date.format("MMMM").toLowerCase(); - return "day" + day + " " + month + currentMonth(date) + even(day - 1); + 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 'month': + return date.format('MMMM').toLowerCase() + currentMonth(date) + even(date.month()); - case "year": + case 'year': var year = date.year(); - return "year" + year + currentYear(date) + even(year); + return 'year' + year + currentYear(date) + even(year); default: - return ""; + return ''; } }; @@ -9186,7 +9123,7 @@ return /******/ (function(modules) { // webpackBootstrap /* 20 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; var Hammer = __webpack_require__(41); var util = __webpack_require__(1); @@ -9316,12 +9253,12 @@ return /******/ (function(modules) { // webpackBootstrap // create and show button var me = this; - var deleteButton = document.createElement("div"); - deleteButton.className = "delete"; - deleteButton.title = "Delete this item"; + var deleteButton = document.createElement('div'); + deleteButton.className = 'delete'; + deleteButton.title = 'Delete this item'; // TODO: be able to destroy the delete button - new Hammer(deleteButton).on("tap", function (event) { + new Hammer(deleteButton).on('tap', function (event) { me.parent.removeFromDataSet(me); event.stopPropagation(); }); @@ -9354,13 +9291,13 @@ return /******/ (function(modules) { // webpackBootstrap if (content !== this.content) { // only replace the content when changed if (content instanceof Element) { - element.innerHTML = ""; + 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); + if (!(this.data.type == 'background' && this.data.content === undefined)) { + throw new Error('Property "content" missing in item ' + this.id); } } @@ -9375,9 +9312,9 @@ return /******/ (function(modules) { // webpackBootstrap */ Item.prototype._updateTitle = function (element) { if (this.data.title != null) { - element.title = this.data.title || ""; + element.title = this.data.title || ''; } else { - element.removeAttribute("title"); + element.removeAttribute('title'); } }; @@ -9392,7 +9329,7 @@ return /******/ (function(modules) { // webpackBootstrap if (Array.isArray(this.options.dataAttributes)) { attributes = this.options.dataAttributes; - } else if (this.options.dataAttributes == "all") { + } else if (this.options.dataAttributes == 'all') { attributes = Object.keys(this.data); } else { return; @@ -9403,9 +9340,9 @@ return /******/ (function(modules) { // webpackBootstrap var value = this.data[name]; if (value != null) { - element.setAttribute("data-" + name, value); + element.setAttribute('data-' + name, value); } else { - element.removeAttribute("data-" + name); + element.removeAttribute('data-' + name); } } } @@ -9431,15 +9368,18 @@ return /******/ (function(modules) { // webpackBootstrap }; module.exports = Item; + // should be implemented by the item + // should be implemented by the item + // should be implemented by the item /***/ }, /* 21 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; var Hammer = __webpack_require__(41); var Item = __webpack_require__(20); @@ -9468,10 +9408,10 @@ return /******/ (function(modules) { // webpackBootstrap // validate data if (data) { if (data.start == undefined) { - throw new Error("Property \"start\" missing in item " + data.id); + throw new Error('Property "start" missing in item ' + data.id); } if (data.end == undefined) { - throw new Error("Property \"end\" missing in item " + data.id); + throw new Error('Property "end" missing in item ' + data.id); } } @@ -9482,7 +9422,7 @@ return /******/ (function(modules) { // webpackBootstrap BackgroundItem.prototype = new Item(null, null, null); - BackgroundItem.prototype.baseClassName = "item background"; + BackgroundItem.prototype.baseClassName = 'item background'; BackgroundItem.prototype.stack = false; /** @@ -9506,12 +9446,12 @@ return /******/ (function(modules) { // webpackBootstrap dom = this.dom; // background box - dom.box = document.createElement("div"); + dom.box = document.createElement('div'); // className is updated in redraw() // contents box - dom.content = document.createElement("div"); - dom.content.className = "content"; + 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, @@ -9523,12 +9463,12 @@ return /******/ (function(modules) { // webpackBootstrap // append DOM to parent DOM if (!this.parent) { - throw new Error("Cannot redraw item: no parent attached"); + 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"); + throw new Error('Cannot redraw item: parent has no background container element'); } background.appendChild(dom.box); } @@ -9545,11 +9485,11 @@ return /******/ (function(modules) { // webpackBootstrap this._updateStyle(this.dom.box); // update class - var className = (this.data.className ? " " + this.data.className : "") + (this.selected ? " selected" : ""); + 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"; + this.overflow = window.getComputedStyle(dom.content).overflow !== 'hidden'; // recalculate size this.props.content.width = this.dom.content.offsetWidth; @@ -9582,9 +9522,9 @@ return /******/ (function(modules) { // webpackBootstrap * @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 onTop = this.options.orientation === 'top'; + this.dom.content.style.top = onTop ? '' : '0'; + this.dom.content.style.bottom = onTop ? '0' : ''; var height; // special positioning for subgroups @@ -9608,8 +9548,8 @@ return /******/ (function(modules) { // webpackBootstrap // 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 = ""; + this.dom.box.style.top = newTop + 'px'; + this.dom.box.style.bottom = ''; } // and when the orientation is bottom: else { @@ -9622,8 +9562,8 @@ return /******/ (function(modules) { // webpackBootstrap } } height = this.parent.subgroups[itemSubgroup].height + margin.item.vertical; - this.dom.box.style.top = newTop + "px"; - this.dom.box.style.bottom = ""; + this.dom.box.style.top = newTop + 'px'; + this.dom.box.style.bottom = ''; } } // and in the case of no subgroups: @@ -9632,16 +9572,16 @@ return /******/ (function(modules) { // webpackBootstrap 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"; + 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.dom.box.style.top = this.parent.top + 'px'; + this.dom.box.style.bottom = ''; } } - this.dom.box.style.height = height + "px"; + this.dom.box.style.height = height + 'px'; }; module.exports = BackgroundItem; @@ -9650,7 +9590,7 @@ return /******/ (function(modules) { // webpackBootstrap /* 22 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; var Item = __webpack_require__(20); var util = __webpack_require__(1); @@ -9680,7 +9620,7 @@ return /******/ (function(modules) { // webpackBootstrap // validate data if (data) { if (data.start == undefined) { - throw new Error("Property \"start\" missing in item " + data); + throw new Error('Property "start" missing in item ' + data); } } @@ -9712,44 +9652,44 @@ return /******/ (function(modules) { // webpackBootstrap dom = this.dom; // create main box - dom.box = document.createElement("DIV"); + 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.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"; + dom.line = document.createElement('DIV'); + dom.line.className = 'line'; // dot on axis - dom.dot = document.createElement("DIV"); - dom.dot.className = "dot"; + dom.dot = document.createElement('DIV'); + dom.dot.className = 'dot'; // attach this item as attribute - dom.box["timeline-item"] = this; + 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"); + 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"); + 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"); + 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"); + if (!background) throw new Error('Cannot redraw item: parent has no axis container element'); axis.appendChild(dom.dot); } this.displayed = true; @@ -9765,10 +9705,10 @@ return /******/ (function(modules) { // webpackBootstrap 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; + 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; @@ -9824,9 +9764,9 @@ return /******/ (function(modules) { // webpackBootstrap var dot = this.dom.dot; // calculate left position of the box - if (align == "right") { + if (align == 'right') { this.left = start - this.width; - } else if (align == "left") { + } else if (align == 'left') { this.left = start; } else { // default or 'center' @@ -9834,13 +9774,13 @@ return /******/ (function(modules) { // webpackBootstrap } // reposition box - box.style.left = this.left + "px"; + box.style.left = this.left + 'px'; // reposition line - line.style.left = start - this.props.line.width / 2 + "px"; + line.style.left = start - this.props.line.width / 2 + 'px'; // reposition dot - dot.style.left = start - this.props.dot.width / 2 + "px"; + dot.style.left = start - this.props.dot.width / 2 + 'px'; }; /** @@ -9853,23 +9793,23 @@ return /******/ (function(modules) { // webpackBootstrap var line = this.dom.line; var dot = this.dom.dot; - if (orientation == "top") { - box.style.top = (this.top || 0) + "px"; + 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 = ""; + 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"; + 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"; + dot.style.top = -this.props.dot.height / 2 + 'px'; }; module.exports = BoxItem; @@ -9878,7 +9818,7 @@ return /******/ (function(modules) { // webpackBootstrap /* 23 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; var Item = __webpack_require__(20); @@ -9908,7 +9848,7 @@ return /******/ (function(modules) { // webpackBootstrap // validate data if (data) { if (data.start == undefined) { - throw new Error("Property \"start\" missing in item " + data); + throw new Error('Property "start" missing in item ' + data); } } @@ -9940,32 +9880,32 @@ return /******/ (function(modules) { // webpackBootstrap dom = this.dom; // background box - dom.point = document.createElement("div"); + 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.content = document.createElement('div'); + dom.content.className = 'content'; dom.point.appendChild(dom.content); // dot at start - dom.dot = document.createElement("div"); + dom.dot = document.createElement('div'); dom.point.appendChild(dom.dot); // attach this item as attribute - dom.point["timeline-item"] = this; + dom.point['timeline-item'] = this; this.dirty = true; } // append DOM to parent DOM if (!this.parent) { - throw new Error("Cannot redraw item: no parent attached"); + 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"); + throw new Error('Cannot redraw item: parent has no foreground container element'); } foreground.appendChild(dom.point); } @@ -9982,9 +9922,9 @@ return /******/ (function(modules) { // webpackBootstrap this._updateStyle(this.dom.point); // 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 className = (this.data.className ? ' ' + this.data.className : '') + (this.selected ? ' selected' : ''); + dom.point.className = 'item point' + className; + dom.dot.className = 'item dot' + className; // recalculate size this.width = dom.point.offsetWidth; @@ -9994,11 +9934,11 @@ return /******/ (function(modules) { // webpackBootstrap this.props.content.height = dom.content.offsetHeight; // resize contents - dom.content.style.marginLeft = 2 * this.props.dot.width + "px"; + 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"; + dom.dot.style.top = (this.height - this.props.dot.height) / 2 + 'px'; + dom.dot.style.left = this.props.dot.width / 2 + 'px'; this.dirty = false; } @@ -10042,7 +9982,7 @@ return /******/ (function(modules) { // webpackBootstrap this.left = start - this.props.dot.width; // reposition point - this.dom.point.style.left = this.left + "px"; + this.dom.point.style.left = this.left + 'px'; }; /** @@ -10053,10 +9993,10 @@ return /******/ (function(modules) { // webpackBootstrap var orientation = this.options.orientation, point = this.dom.point; - if (orientation == "top") { - point.style.top = this.top + "px"; + if (orientation == 'top') { + point.style.top = this.top + 'px'; } else { - point.style.top = this.parent.height - this.top - this.height + "px"; + point.style.top = this.parent.height - this.top - this.height + 'px'; } }; @@ -10066,7 +10006,7 @@ return /******/ (function(modules) { // webpackBootstrap /* 24 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; var Hammer = __webpack_require__(41); var Item = __webpack_require__(20); @@ -10092,10 +10032,10 @@ return /******/ (function(modules) { // webpackBootstrap // validate data if (data) { if (data.start == undefined) { - throw new Error("Property \"start\" missing in item " + data.id); + throw new Error('Property "start" missing in item ' + data.id); } if (data.end == undefined) { - throw new Error("Property \"end\" missing in item " + data.id); + throw new Error('Property "end" missing in item ' + data.id); } } @@ -10104,7 +10044,7 @@ return /******/ (function(modules) { // webpackBootstrap RangeItem.prototype = new Item(null, null, null); - RangeItem.prototype.baseClassName = "item range"; + RangeItem.prototype.baseClassName = 'item range'; /** * Check whether this item is visible inside given range @@ -10127,28 +10067,28 @@ return /******/ (function(modules) { // webpackBootstrap dom = this.dom; // background box - dom.box = document.createElement("div"); + dom.box = document.createElement('div'); // className is updated in redraw() // contents box - dom.content = document.createElement("div"); - dom.content.className = "content"; + dom.content = document.createElement('div'); + dom.content.className = 'content'; dom.box.appendChild(dom.content); // attach this item as attribute - dom.box["timeline-item"] = this; + 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"); + 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"); + throw new Error('Cannot redraw item: parent has no foreground container element'); } foreground.appendChild(dom.box); } @@ -10165,19 +10105,19 @@ return /******/ (function(modules) { // webpackBootstrap this._updateStyle(this.dom.box); // update class - var className = (this.data.className ? " " + this.data.className : "") + (this.selected ? " selected" : ""); + 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"; + 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.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.dom.content.style.maxWidth = ''; this.dirty = false; } @@ -10250,20 +10190,20 @@ return /******/ (function(modules) { // webpackBootstrap 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"; + 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"; + 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"; + 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"; + case 'center': + this.dom.content.style.left = Math.max((boxWidth - contentWidth - 2 * this.options.padding) / 2, 0) + 'px'; break; default: @@ -10283,7 +10223,7 @@ return /******/ (function(modules) { // webpackBootstrap contentLeft = 0; } } - this.dom.content.style.left = contentLeft + "px"; + this.dom.content.style.left = contentLeft + 'px'; } }; @@ -10295,10 +10235,10 @@ return /******/ (function(modules) { // webpackBootstrap var orientation = this.options.orientation, box = this.dom.box; - if (orientation == "top") { - box.style.top = this.top + "px"; + if (orientation == 'top') { + box.style.top = this.top + 'px'; } else { - box.style.top = this.parent.height - this.top - this.height + "px"; + box.style.top = this.parent.height - this.top - this.height + 'px'; } }; @@ -10309,8 +10249,8 @@ return /******/ (function(modules) { // webpackBootstrap 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"; + var dragLeft = document.createElement('div'); + dragLeft.className = 'drag-left'; dragLeft.dragLeftItem = this; this.dom.box.appendChild(dragLeft); @@ -10331,8 +10271,8 @@ return /******/ (function(modules) { // webpackBootstrap 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"; + var dragRight = document.createElement('div'); + dragRight.className = 'drag-right'; dragRight.dragRightItem = this; this.dom.box.appendChild(dragRight); @@ -10352,13 +10292,13 @@ return /******/ (function(modules) { // webpackBootstrap /* 25 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; - /** * Prototype for visual components * @param {{dom: Object, domProps: Object, emitter: Emitter, range: Range}} [body] * @param {Object} [options] */ + "use strict"; + function Component(body, options) { this.options = null; this.props = null; @@ -10405,18 +10345,19 @@ return /******/ (function(modules) { // webpackBootstrap }; module.exports = Component; + // should be implemented by the component /***/ }, /* 26 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; var util = __webpack_require__(1); var Component = __webpack_require__(25); var moment = __webpack_require__(40); - var locales = __webpack_require__(44); + var locales = __webpack_require__(45); /** * A current time bar @@ -10434,7 +10375,7 @@ return /******/ (function(modules) { // webpackBootstrap showCurrentTime: true, locales: locales, - locale: "en" + locale: 'en' }; this.options = util.extend({}, this.defaultOptions); this.offset = 0; @@ -10451,11 +10392,11 @@ return /******/ (function(modules) { // webpackBootstrap * @private */ CurrentTime.prototype._create = function () { - var bar = document.createElement("div"); - bar.className = "currenttime"; - bar.style.position = "absolute"; - bar.style.top = "0px"; - bar.style.height = "100%"; + var bar = document.createElement('div'); + bar.className = 'currenttime'; + bar.style.position = 'absolute'; + bar.style.top = '0px'; + bar.style.height = '100%'; this.bar = bar; }; @@ -10478,7 +10419,7 @@ return /******/ (function(modules) { // webpackBootstrap CurrentTime.prototype.setOptions = function (options) { if (options) { // copy all options that we know - util.selectiveExtend(["showCurrentTime", "locale", "locales"], this.options, options); + util.selectiveExtend(['showCurrentTime', 'locale', 'locales'], this.options, options); } }; @@ -10503,10 +10444,10 @@ return /******/ (function(modules) { // webpackBootstrap 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"); + var title = locale.current + ' ' + locale.time + ': ' + moment(now).format('dddd, MMMM Do YYYY, H:mm:ss'); title = title.charAt(0).toUpperCase() + title.substring(1); - this.bar.style.left = x + "px"; + this.bar.style.left = x + 'px'; this.bar.title = title; } else { // remove the line from the DOM @@ -10560,7 +10501,7 @@ return /******/ (function(modules) { // webpackBootstrap * ISO date string. */ CurrentTime.prototype.setCurrentTime = function (time) { - var t = util.convert(time, "Date").valueOf(); + var t = util.convert(time, 'Date').valueOf(); var now = new Date().valueOf(); this.offset = t - now; this.redraw(); @@ -10580,13 +10521,13 @@ return /******/ (function(modules) { // webpackBootstrap /* 27 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; var Hammer = __webpack_require__(41); var util = __webpack_require__(1); var Component = __webpack_require__(25); var moment = __webpack_require__(40); - var locales = __webpack_require__(44); + var locales = __webpack_require__(45); /** * A custom time bar @@ -10604,7 +10545,7 @@ return /******/ (function(modules) { // webpackBootstrap this.defaultOptions = { showCustomTime: false, locales: locales, - locale: "en", + locale: 'en', id: 0 }; this.options = util.extend({}, this.defaultOptions); @@ -10633,7 +10574,7 @@ return /******/ (function(modules) { // webpackBootstrap CustomTime.prototype.setOptions = function (options) { if (options) { // copy all options that we know - util.selectiveExtend(["showCustomTime", "locale", "locales", "id"], this.options, options); + util.selectiveExtend(['showCustomTime', 'locale', 'locales', 'id'], this.options, options); // Triggered by addCustomTimeBar, redraw to add new bar if (this.options.id) { @@ -10647,26 +10588,26 @@ return /******/ (function(modules) { // webpackBootstrap * @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%"; + 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"; + var drag = document.createElement('div'); + drag.style.position = 'relative'; + drag.style.top = '0px'; + drag.style.left = '-10px'; + drag.style.height = '100%'; + drag.style.width = '20px'; bar.appendChild(drag); // attach event listeners this.hammer = new Hammer(drag); - this.hammer.on("panstart", this._onDragStart.bind(this)); - this.hammer.on("panmove", this._onDrag.bind(this)); - this.hammer.on("panend", this._onDragEnd.bind(this)); + this.hammer.on('panstart', this._onDragStart.bind(this)); + this.hammer.on('panmove', this._onDrag.bind(this)); + this.hammer.on('panend', this._onDragEnd.bind(this)); // TODO: cleanup //this.hammer.on('pan', function (event) { // event.preventDefault(); @@ -10704,10 +10645,10 @@ return /******/ (function(modules) { // webpackBootstrap 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"); + 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.style.left = x + 'px'; this.bar.title = title; } else { // remove the line from the DOM @@ -10724,7 +10665,7 @@ return /******/ (function(modules) { // webpackBootstrap * @param {Date | number | string} time */ CustomTime.prototype.setCustomTime = function (time) { - this.customTime = util.convert(time, "Date"); + this.customTime = util.convert(time, 'Date'); this.redraw(); }; @@ -10762,7 +10703,7 @@ return /******/ (function(modules) { // webpackBootstrap this.setCustomTime(time); // fire a timechange event - this.body.emitter.emit("timechange", { + this.body.emitter.emit('timechange', { id: this.options.id, time: new Date(this.customTime.valueOf()) }); @@ -10779,7 +10720,7 @@ return /******/ (function(modules) { // webpackBootstrap if (!this.eventParams.dragging) return; // fire a timechanged event - this.body.emitter.emit("timechanged", { + this.body.emitter.emit('timechanged', { id: this.options.id, time: new Date(this.customTime.valueOf()) }); @@ -10793,7 +10734,7 @@ return /******/ (function(modules) { // webpackBootstrap /* 28 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; var util = __webpack_require__(1); var DOMutil = __webpack_require__(2); @@ -10813,7 +10754,7 @@ return /******/ (function(modules) { // webpackBootstrap this.body = body; this.defaultOptions = { - orientation: "left", // supported: 'left', 'right' + orientation: 'left', // supported: 'left', 'right' showMinorLabels: true, showMajorLabels: true, icons: true, @@ -10822,7 +10763,7 @@ return /******/ (function(modules) { // webpackBootstrap labelOffsetX: 10, labelOffsetY: 2, iconWidth: 20, - width: "40px", + width: '40px', visible: true, alignZeros: true, customRange: { @@ -10856,7 +10797,7 @@ return /******/ (function(modules) { // webpackBootstrap this.conversionFactor = 1; this.setOptions(options); - this.width = Number(("" + this.options.width).replace("px", "")); + this.width = Number(('' + this.options.width).replace('px', '')); this.minWidth = this.width; this.height = this.linegraphSVG.offsetHeight; this.hidden = false; @@ -10870,7 +10811,6 @@ return /******/ (function(modules) { // webpackBootstrap this.svgElements = {}; this.iconsRemoved = false; - this.groups = {}; this.amountOfGroups = 0; @@ -10878,14 +10818,13 @@ return /******/ (function(modules) { // webpackBootstrap this._create(); var me = this; - this.body.emitter.on("verticalDrag", function () { - me.dom.lineContainer.style.top = me.body.domProps.scrollTop + "px"; + this.body.emitter.on('verticalDrag', function () { + me.dom.lineContainer.style.top = me.body.domProps.scrollTop + 'px'; }); } DataAxis.prototype = new Component(); - DataAxis.prototype.addGroup = function (label, graphOptions) { if (!this.groups.hasOwnProperty(label)) { this.groups[label] = graphOptions; @@ -10904,17 +10843,16 @@ return /******/ (function(modules) { // webpackBootstrap } }; - 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"]; + 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", "")); + this.minWidth = Number(('' + this.options.width).replace('px', '')); if (redraw == true && this.dom.frame) { this.hide(); @@ -10923,27 +10861,26 @@ return /******/ (function(modules) { // webpackBootstrap } }; - /** * Create the HTML DOM for the DataAxis */ DataAxis.prototype._create = function () { - this.dom.frame = document.createElement("div"); + 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 = document.createElement('div'); + this.dom.lineContainer.style.width = '100%'; this.dom.lineContainer.style.height = this.height; - this.dom.lineContainer.style.position = "relative"; + this.dom.lineContainer.style.position = 'relative'; // create svg element for graph drawing. - this.svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); - this.svg.style.position = "absolute"; - this.svg.style.top = "0px"; - this.svg.style.height = "100%"; - this.svg.style.width = "100%"; - this.svg.style.display = "block"; + 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); }; @@ -10956,7 +10893,7 @@ return /******/ (function(modules) { // webpackBootstrap var iconOffset = 4; var y = iconOffset + 0.5 * iconHeight; - if (this.options.orientation == "left") { + if (this.options.orientation == 'left') { x = iconOffset; } else { x = this.width - iconWidth - iconOffset; @@ -10989,7 +10926,7 @@ return /******/ (function(modules) { // webpackBootstrap DataAxis.prototype.show = function () { this.hidden = false; if (!this.dom.frame.parentNode) { - if (this.options.orientation == "left") { + if (this.options.orientation == 'left') { this.body.dom.left.appendChild(this.dom.frame); } else { this.body.dom.right.appendChild(this.dom.frame); @@ -11040,7 +10977,7 @@ return /******/ (function(modules) { // webpackBootstrap var activeGroups = 0; // Make sure the line container adheres to the vertical scrolling. - this.dom.lineContainer.style.top = this.body.domProps.scrollTop + "px"; + this.dom.lineContainer.style.top = this.body.domProps.scrollTop + 'px'; for (var groupId in this.groups) { if (this.groups.hasOwnProperty(groupId)) { @@ -11053,17 +10990,17 @@ return /******/ (function(modules) { // webpackBootstrap this.hide(); } else { this.show(); - this.height = Number(this.linegraphSVG.style.height.replace("px", "")); + this.height = Number(this.linegraphSVG.style.height.replace('px', '')); // svg offsetheight did not work in firefox and explorer... - this.dom.lineContainer.style.height = this.height + "px"; - this.width = this.options.visible == true ? Number(("" + this.options.width).replace("px", "")) : 0; + this.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; // update classname - frame.className = "dataaxis"; + frame.className = 'dataaxis'; // calculate character width and height this._calculateCharSize(); @@ -11082,21 +11019,21 @@ return /******/ (function(modules) { // webpackBootstrap props.majorLineHeight = 1; // take frame offline while updating (is almost twice as fast) - if (orientation == "left") { - frame.style.top = "0"; - frame.style.left = "0"; - frame.style.bottom = ""; - frame.style.width = this.width + "px"; - frame.style.height = this.height + "px"; + 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"; + 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; } @@ -11167,7 +11104,6 @@ return /******/ (function(modules) { // webpackBootstrap amountOfSteps += 0.25; } - this.valueAtZero = step.marginEnd; var marginStartPos = 0; @@ -11189,16 +11125,16 @@ return /******/ (function(modules) { // webpackBootstrap 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); + 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._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); + this._redrawLine(y, orientation, 'grid horizontal major', this.options.majorLinesOffset, this.props.majorLineWidth); } else { - this._redrawLine(y, orientation, "grid horizontal minor", this.options.minorLinesOffset, this.props.minorLineWidth); + this._redrawLine(y, orientation, 'grid horizontal minor', this.options.minorLinesOffset, this.props.minorLineWidth); } if (this.master == true && step.current == 0) { @@ -11224,7 +11160,7 @@ return /******/ (function(modules) { // webpackBootstrap // this will resize the yAxis to accommodate the labels. if (this.maxLabelSize > this.width - offset && this.options.visible == true) { this.width = this.maxLabelSize + offset; - this.options.width = this.width + "px"; + this.options.width = this.width + 'px'; DOMutil.cleanupElements(this.DOMelements.lines); DOMutil.cleanupElements(this.DOMelements.labels); this.redraw(); @@ -11233,7 +11169,7 @@ return /******/ (function(modules) { // webpackBootstrap // this will resize the yAxis if it is too big for the labels. else if (this.maxLabelSize < this.width - offset && this.options.visible == true && this.width > this.minWidth) { this.width = Math.max(this.minWidth, this.maxLabelSize + offset); - this.options.width = this.width + "px"; + this.options.width = this.width + 'px'; DOMutil.cleanupElements(this.DOMelements.lines); DOMutil.cleanupElements(this.DOMelements.labels); this.redraw(); @@ -11264,20 +11200,20 @@ return /******/ (function(modules) { // webpackBootstrap */ 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(); + 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"; + 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.right = '-' + this.options.labelOffsetX + 'px'; + label.style.textAlign = 'left'; } - label.style.top = y - 0.5 * characterHeight + this.options.labelOffsetY + "px"; + label.style.top = y - 0.5 * characterHeight + this.options.labelOffsetY + 'px'; - text += ""; + text += ''; var largestWidth = Math.max(this.props.majorCharWidth, this.props.minorCharWidth); if (this.maxLabelSize < text.length * largestWidth) { @@ -11295,18 +11231,18 @@ return /******/ (function(modules) { // webpackBootstrap */ 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(); + var line = DOMutil.getDOMElement('div', this.DOMelements.lines, this.dom.lineContainer); //this.dom.redundant.lines.shift(); line.className = className; - line.innerHTML = ""; + line.innerHTML = ''; - if (orientation == "left") { - line.style.left = this.width - offset + "px"; + if (orientation == 'left') { + line.style.left = this.width - offset + 'px'; } else { - line.style.right = this.width - offset + "px"; + line.style.right = this.width - offset + 'px'; } - line.style.width = width + "px"; - line.style.top = y + "px"; + line.style.width = width + 'px'; + line.style.top = y + 'px'; } }; @@ -11320,8 +11256,8 @@ return /******/ (function(modules) { // webpackBootstrap // 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; + var title = DOMutil.getDOMElement('div', this.DOMelements.title, this.dom.frame); + title.className = 'yAxis title ' + orientation; title.innerHTML = this.options.title[orientation].text; // Add style - if provided @@ -11329,22 +11265,19 @@ return /******/ (function(modules) { // webpackBootstrap util.addCssText(title, this.options.title[orientation].style); } - if (orientation == "left") { - title.style.left = this.props.titleCharHeight + "px"; + if (orientation == 'left') { + title.style.left = this.props.titleCharHeight + 'px'; } else { - title.style.right = this.props.titleCharHeight + "px"; + title.style.right = this.props.titleCharHeight + 'px'; } - title.style.width = this.height + "px"; + title.style.width = this.height + 'px'; } // we need to clean up in case we did not use all elements. DOMutil.cleanupElements(this.DOMelements.title); }; - - - /** * 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. @@ -11352,10 +11285,10 @@ return /******/ (function(modules) { // webpackBootstrap */ 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"; + 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); @@ -11365,10 +11298,10 @@ return /******/ (function(modules) { // webpackBootstrap this.dom.frame.removeChild(measureCharMinor); } - if (!("majorCharHeight" in this.props)) { - var textMajor = document.createTextNode("0"); - var measureCharMajor = document.createElement("div"); - measureCharMajor.className = "yAxis major measure"; + 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); @@ -11378,10 +11311,10 @@ return /******/ (function(modules) { // webpackBootstrap this.dom.frame.removeChild(measureCharMajor); } - if (!("titleCharHeight" in this.props)) { - var textTitle = document.createTextNode("0"); - var measureCharTitle = document.createElement("div"); - measureCharTitle.className = "yAxis title measure"; + 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); @@ -11398,13 +11331,13 @@ return /******/ (function(modules) { // webpackBootstrap /* 29 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; var util = __webpack_require__(1); var DOMutil = __webpack_require__(2); - var Line = __webpack_require__(45); - var Bar = __webpack_require__(46); - var Points = __webpack_require__(47); + var Line = __webpack_require__(46); + var Bar = __webpack_require__(47); + var Points = __webpack_require__(48); /** * /** @@ -11418,7 +11351,7 @@ return /******/ (function(modules) { // webpackBootstrap */ function GraphGroup(group, groupId, options, groupsUsingDefaultStyles) { this.id = groupId; - var fields = ["sampling", "style", "sort", "yAxisOrientation", "barChart", "drawPoints", "shaded", "catmullRom"]; + var fields = ['sampling', 'style', 'sort', 'yAxisOrientation', 'barChart', 'drawPoints', 'shaded', 'catmullRom']; this.options = util.selectiveBridgeObject(fields, options); this.usingDefaultStyle = group.className === undefined; this.groupsUsingDefaultStyles = groupsUsingDefaultStyles; @@ -11431,7 +11364,6 @@ return /******/ (function(modules) { // webpackBootstrap this.visible = group.visible === undefined ? true : group.visible; } - /** * this loads a reference to all items in this group into this group. * @param {array} items @@ -11449,7 +11381,6 @@ return /******/ (function(modules) { // webpackBootstrap } }; - /** * this is used for plotting barcharts, this way, we only have to calculate it once. * @param pos @@ -11458,29 +11389,28 @@ return /******/ (function(modules) { // webpackBootstrap this.zeroPosition = pos; }; - /** * 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"]; + var fields = ['sampling', 'style', 'sort', 'yAxisOrientation', 'barChart']; 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, 'catmullRom'); + util.mergeOptions(this.options, options, 'drawPoints'); + util.mergeOptions(this.options, options, 'shaded'); if (options.catmullRom) { - if (typeof options.catmullRom == "object") { + if (typeof options.catmullRom == 'object') { if (options.catmullRom.parametrization) { - if (options.catmullRom.parametrization == "uniform") { + if (options.catmullRom.parametrization == 'uniform') { this.options.catmullRom.alpha = 0; - } else if (options.catmullRom.parametrization == "chordal") { + } else if (options.catmullRom.parametrization == 'chordal') { this.options.catmullRom.alpha = 1; } else { - this.options.catmullRom.parametrization = "centripetal"; + this.options.catmullRom.parametrization = 'centripetal'; this.options.catmullRom.alpha = 0.5; } } @@ -11488,30 +11418,28 @@ return /******/ (function(modules) { // webpackBootstrap } } - if (this.options.style == "line") { + if (this.options.style == 'line') { this.type = new Line(this.id, this.options); - } else if (this.options.style == "bar") { + } else if (this.options.style == 'bar') { this.type = new Bar(this.id, this.options); - } else if (this.options.style == "points") { + } else if (this.options.style == 'points') { this.type = new Points(this.id, this.options); } }; - /** * 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.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); }; - /** * draw the icon for the legend. * @@ -11526,29 +11454,29 @@ return /******/ (function(modules) { // webpackBootstrap var fillHeight = iconHeight * 0.5; var path, fillPath; - var outline = DOMutil.getSVGElement("rect", JSONcontainer, SVGcontainer); - outline.setAttributeNS(null, "x", x); - outline.setAttributeNS(null, "y", y - fillHeight); - outline.setAttributeNS(null, "width", iconWidth); - outline.setAttributeNS(null, "height", 2 * fillHeight); - outline.setAttributeNS(null, "class", "outline"); + var outline = DOMutil.getSVGElement('rect', JSONcontainer, SVGcontainer); + outline.setAttributeNS(null, 'x', x); + outline.setAttributeNS(null, 'y', y - fillHeight); + outline.setAttributeNS(null, 'width', iconWidth); + outline.setAttributeNS(null, 'height', 2 * fillHeight); + outline.setAttributeNS(null, 'class', 'outline'); - if (this.options.style == "line") { - path = DOMutil.getSVGElement("path", JSONcontainer, SVGcontainer); - path.setAttributeNS(null, "class", this.className); + 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, 'style', this.style); } - path.setAttributeNS(null, "d", "M" + x + "," + y + " L" + (x + iconWidth) + "," + y + ""); + path.setAttributeNS(null, 'd', 'M' + x + ',' + y + ' L' + (x + iconWidth) + ',' + y + ''); if (this.options.shaded.enabled == true) { - fillPath = DOMutil.getSVGElement("path", JSONcontainer, SVGcontainer); - if (this.options.shaded.orientation == "top") { - fillPath.setAttributeNS(null, "d", "M" + x + ", " + (y - fillHeight) + "L" + x + "," + y + " L" + (x + iconWidth) + "," + y + " L" + (x + iconWidth) + "," + (y - fillHeight)); + fillPath = 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, 'd', 'M' + x + ',' + y + ' ' + 'L' + x + ',' + (y + fillHeight) + ' ' + 'L' + (x + iconWidth) + ',' + (y + fillHeight) + 'L' + (x + iconWidth) + ',' + y); } - fillPath.setAttributeNS(null, "class", this.className + " iconFill"); + fillPath.setAttributeNS(null, 'class', this.className + ' iconFill'); } if (this.options.drawPoints.enabled == true) { @@ -11561,12 +11489,11 @@ return /******/ (function(modules) { // webpackBootstrap 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); + 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); } }; - /** * return the legend entree for this group. * @@ -11575,7 +11502,7 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {{icon: HTMLElement, label: (group.content|*|string), orientation: (.options.yAxisOrientation|*)}} */ GraphGroup.prototype.getLegend = function (iconWidth, iconHeight) { - var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); this.drawIcon(0, 0.5 * iconHeight, [], svg, iconWidth, iconHeight); return { icon: svg, label: this.content, orientation: this.options.yAxisOrientation }; }; @@ -11588,14 +11515,13 @@ return /******/ (function(modules) { // webpackBootstrap this.type.draw(dataset, group, framework); }; - module.exports = GraphGroup; /***/ }, /* 30 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; var util = __webpack_require__(1); var stack = __webpack_require__(18); @@ -11631,7 +11557,7 @@ return /******/ (function(modules) { // webpackBootstrap }; 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 () { + this.itemSet.body.emitter.on('checkRangedItems', function () { me.checkRangedItems = true; }); @@ -11645,32 +11571,32 @@ return /******/ (function(modules) { // webpackBootstrap * @private */ Group.prototype._create = function () { - var label = document.createElement("div"); - label.className = "vlabel"; + var label = document.createElement('div'); + label.className = 'vlabel'; this.dom.label = label; - var inner = document.createElement("div"); - inner.className = "inner"; + 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; + 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.background = document.createElement('div'); + this.dom.background.className = 'group'; - this.dom.axis = document.createElement("div"); - this.dom.axis.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.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); }; @@ -11686,16 +11612,16 @@ return /******/ (function(modules) { // webpackBootstrap } else if (content !== undefined && content !== null) { this.dom.inner.innerHTML = content; } else { - this.dom.inner.innerHTML = this.groupId || ""; // groupId can be null + this.dom.inner.innerHTML = this.groupId || ''; // groupId can be null } // update title - this.dom.label.title = data && data.title || ""; + this.dom.label.title = data && data.title || ''; if (!this.dom.inner.firstChild) { - util.addClassName(this.dom.inner, "hidden"); + util.addClassName(this.dom.inner, 'hidden'); } else { - util.removeClassName(this.dom.inner, "hidden"); + util.removeClassName(this.dom.inner, 'hidden'); } // update className @@ -11733,7 +11659,6 @@ return /******/ (function(modules) { // webpackBootstrap return this.props.label.width; }; - /** * Repaint this group * @param {{start: number, end: number}} range @@ -11777,16 +11702,16 @@ return /******/ (function(modules) { // webpackBootstrap this.top = foreground.offsetTop; this.left = foreground.offsetLeft; this.width = foreground.offsetWidth; - resized = util.updateProperty(this, "height", height) || resized; + 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; + 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"; + 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++) { @@ -11912,14 +11837,14 @@ return /******/ (function(modules) { // webpackBootstrap Group.prototype.orderSubgroups = function () { if (this.subgroupOrderer !== undefined) { var sortArray = []; - if (typeof this.subgroupOrderer == "string") { + 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") { + } else if (typeof this.subgroupOrderer == 'function') { for (var subgroup in this.subgroups) { sortArray.push(this.subgroups[subgroup].items[0].data); } @@ -11957,7 +11882,6 @@ return /******/ (function(modules) { // webpackBootstrap // TODO: also remove from ordered items? }; - /** * Remove an item from the corresponding DataSet * @param {Item} item @@ -11966,7 +11890,6 @@ return /******/ (function(modules) { // webpackBootstrap this.itemSet.removeItem(item.id); }; - /** * Reorder the items */ @@ -11990,7 +11913,6 @@ return /******/ (function(modules) { // webpackBootstrap stack.orderByEnd(this.orderedItems.byEnd); }; - /** * Update the visible items * @param {{byStart: Item[], byEnd: Item[]}} orderedItems All items ordered by start date and by end date @@ -12008,7 +11930,7 @@ return /******/ (function(modules) { // webpackBootstrap var item, i; // this function is used to do the binary search. - var searchFunction = function (value) { + var searchFunction = function searchFunction(value) { if (value < lowerBound) { return -1; } else if (value <= upperBound) { @@ -12028,7 +11950,7 @@ return /******/ (function(modules) { // webpackBootstrap } // we do a binary search for the items that have only start values. - var initialPosByStart = util.binarySearchCustom(orderedItems.byStart, searchFunction, "data", "start"); + var initialPosByStart = util.binarySearchCustom(orderedItems.byStart, searchFunction, 'data', 'start'); // 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) { @@ -12044,7 +11966,7 @@ return /******/ (function(modules) { // webpackBootstrap } } else { // we do a binary search for the items that have defined end times. - var initialPosByEnd = util.binarySearchCustom(orderedItems.byEnd, searchFunction, "data", "end"); + var initialPosByEnd = util.binarySearchCustom(orderedItems.byEnd, searchFunction, 'data', 'end'); // 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) { @@ -12052,7 +11974,6 @@ return /******/ (function(modules) { // webpackBootstrap }); } - // finally, we reposition all the visible items. for (i = 0; i < visibleItems.length; i++) { item = visibleItems[i]; @@ -12108,7 +12029,6 @@ return /******/ (function(modules) { // webpackBootstrap } }; - /** * this function is very similar to the _checkIfInvisible() but it does not * return booleans, hides the item if it should not be seen and always adds to @@ -12131,7 +12051,6 @@ return /******/ (function(modules) { // webpackBootstrap } }; - /** * this function is very similar to the _checkIfInvisible() but it does not * return booleans, hides the item if it should not be seen and always adds to @@ -12154,15 +12073,13 @@ return /******/ (function(modules) { // webpackBootstrap } }; - - module.exports = Group; /***/ }, /* 31 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; var util = __webpack_require__(1); var Group = __webpack_require__(30); @@ -12200,7 +12117,7 @@ return /******/ (function(modules) { // webpackBootstrap this.width = this.dom.background.offsetWidth; // apply new height (just always zero for BackgroundGroup - this.dom.background.style.height = "0"; + this.dom.background.style.height = '0'; // 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++) { @@ -12226,7 +12143,7 @@ return /******/ (function(modules) { // webpackBootstrap /* 32 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; var Hammer = __webpack_require__(41); var util = __webpack_require__(1); @@ -12241,9 +12158,8 @@ return /******/ (function(modules) { // webpackBootstrap var RangeItem = __webpack_require__(24); var BackgroundItem = __webpack_require__(21); - - var UNGROUPED = "__ungrouped__"; // reserved group id for ungrouped items - var BACKGROUND = "__background__"; // reserved group id for background items without group + var UNGROUPED = '__ungrouped__'; // reserved group id for ungrouped items + var BACKGROUND = '__background__'; // reserved group id for background items without group /** * An ItemSet holds a set of items and ranges which can be displayed in a @@ -12259,8 +12175,8 @@ return /******/ (function(modules) { // webpackBootstrap this.defaultOptions = { type: null, // 'box', 'point', 'range', 'background' - orientation: "bottom", // 'top' or 'bottom' - align: "auto", // alignment of box items + orientation: 'bottom', // 'top' or 'bottom' + align: 'auto', // alignment of box items stack: true, groupOrder: null, @@ -12274,19 +12190,19 @@ return /******/ (function(modules) { // webpackBootstrap snap: TimeStep.snap, - onAdd: function (item, callback) { + onAdd: function onAdd(item, callback) { callback(item); }, - onUpdate: function (item, callback) { + onUpdate: function onUpdate(item, callback) { callback(item); }, - onMove: function (item, callback) { + onMove: function onMove(item, callback) { callback(item); }, - onRemove: function (item, callback) { + onRemove: function onRemove(item, callback) { callback(item); }, - onMoving: function (item, callback) { + onMoving: function onMoving(item, callback) { callback(item); }, @@ -12305,7 +12221,7 @@ return /******/ (function(modules) { // webpackBootstrap // options for getting items from the DataSet with the correct type this.itemOptions = { - type: { start: "Date", end: "Date" } + type: { start: 'Date', end: 'Date' } }; this.conversion = { @@ -12322,26 +12238,26 @@ return /******/ (function(modules) { // webpackBootstrap // listeners for the DataSet of the items this.itemListeners = { - add: function (event, params, senderId) { + add: function add(event, params, senderId) { me._onAdd(params.items); }, - update: function (event, params, senderId) { + update: function update(event, params, senderId) { me._onUpdate(params.items); }, - remove: function (event, params, senderId) { + remove: function remove(event, params, senderId) { me._onRemove(params.items); } }; // listeners for the DataSet of the groups this.groupListeners = { - add: function (event, params, senderId) { + add: function add(event, params, senderId) { me._onAddGroups(params.items); }, - update: function (event, params, senderId) { + update: function update(event, params, senderId) { me._onUpdateGroups(params.items); }, - remove: function (event, params, senderId) { + remove: function remove(event, params, senderId) { me._onRemoveGroups(params.items); } }; @@ -12375,31 +12291,31 @@ return /******/ (function(modules) { // webpackBootstrap * Create the HTML DOM for the ItemSet */ ItemSet.prototype._create = function () { - var frame = document.createElement("div"); - frame.className = "itemset"; - frame["timeline-itemset"] = this; + var frame = document.createElement('div'); + frame.className = 'itemset'; + frame['timeline-itemset'] = this; this.dom.frame = frame; // create background panel - var background = document.createElement("div"); - background.className = "background"; + var background = document.createElement('div'); + background.className = 'background'; frame.appendChild(background); this.dom.background = background; // create foreground panel - var foreground = document.createElement("div"); - foreground.className = "foreground"; + var foreground = document.createElement('div'); + foreground.className = 'foreground'; frame.appendChild(foreground); this.dom.foreground = foreground; // create axis panel - var axis = document.createElement("div"); - axis.className = "axis"; + var axis = document.createElement('div'); + axis.className = 'axis'; this.dom.axis = axis; // create labelset - var labelSet = document.createElement("div"); - labelSet.className = "labelset"; + var labelSet = document.createElement('div'); + labelSet.className = 'labelset'; this.dom.labelSet = labelSet; // create ungrouped Group @@ -12417,23 +12333,23 @@ return /******/ (function(modules) { // webpackBootstrap this.hammer = new Hammer(this.body.dom.centerContainer); // drag items when selected - this.hammer.on("hammer.input", (function (event) { + this.hammer.on('hammer.input', (function (event) { if (event.isFirst) { this._onTouch(event); } }).bind(this)); - this.hammer.on("panstart", this._onDragStart.bind(this)); - this.hammer.on("panmove", this._onDrag.bind(this)); - this.hammer.on("panend", this._onDragEnd.bind(this)); + this.hammer.on('panstart', this._onDragStart.bind(this)); + this.hammer.on('panmove', this._onDrag.bind(this)); + this.hammer.on('panend', this._onDragEnd.bind(this)); // single select (or unselect) when tapping an item - this.hammer.on("tap", this._onSelectItem.bind(this)); + this.hammer.on('tap', this._onSelectItem.bind(this)); // multi select when holding mouse/touch, or on ctrl+click - this.hammer.on("press", this._onMultiSelectItem.bind(this)); + this.hammer.on('press', this._onMultiSelectItem.bind(this)); // add item on doubletap - this.hammer.on("doubletap", this._onAddItem.bind(this)); + this.hammer.on('doubletap', this._onAddItem.bind(this)); // attach to the DOM this.show(); @@ -12506,35 +12422,35 @@ return /******/ (function(modules) { // webpackBootstrap 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"]; + var fields = ['type', 'align', 'orientation', 'padding', 'stack', 'selectable', 'groupOrder', 'dataAttributes', 'template', 'hide', 'snap']; util.selectiveExtend(fields, this.options, options); - if ("margin" in options) { - if (typeof options.margin === "number") { + 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") { + } 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); + } else if (typeof options.margin.item === 'object') { + util.selectiveExtend(['horizontal', 'vertical'], this.options.margin.item, options.margin.item); } } } } - if ("editable" in options) { - if (typeof options.editable === "boolean") { + 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); + } else if (typeof options.editable === 'object') { + util.selectiveExtend(['updateTime', 'updateGroup', 'add', 'remove'], this.options.editable, options.editable); } } @@ -12543,12 +12459,12 @@ return /******/ (function(modules) { // webpackBootstrap var fn = options[name]; if (fn) { if (!(fn instanceof Function)) { - throw new Error("option " + name + " must be a function " + name + "(item, callback)"); + 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); + ['onAdd', 'onUpdate', 'onRemove', 'onMove', 'onMoving'].forEach(addCallback); // force the itemSet to refresh: options like orientation and margins may be changed this.markDirty(); @@ -12732,7 +12648,7 @@ return /******/ (function(modules) { // webpackBootstrap this.props.left = this.body.domProps.left.width + this.body.domProps.border.left; // update class name - frame.className = "itemset" + (editable ? " editable" : ""); + frame.className = 'itemset' + (editable ? ' editable' : ''); // reorder the groups (if needed) resized = this._orderGroups() || resized; @@ -12779,8 +12695,8 @@ return /******/ (function(modules) { // webpackBootstrap 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"; + 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; @@ -12794,7 +12710,7 @@ return /******/ (function(modules) { // webpackBootstrap * @private */ ItemSet.prototype._firstGroup = function () { - var firstGroupIndex = this.options.orientation == "top" ? 0 : this.groupIds.length - 1; + var firstGroupIndex = this.options.orientation == 'top' ? 0 : this.groupIds.length - 1; var firstGroupId = this.groupIds[firstGroupIndex]; var firstGroup = this.groups[firstGroupId] || this.groups[UNGROUPED]; @@ -12870,7 +12786,7 @@ return /******/ (function(modules) { // webpackBootstrap } else if (items instanceof DataSet || items instanceof DataView) { this.itemsData = items; } else { - throw new TypeError("Data must be an instance of DataSet or DataView"); + throw new TypeError('Data must be an instance of DataSet or DataView'); } if (oldItemsData) { @@ -12934,7 +12850,7 @@ return /******/ (function(modules) { // webpackBootstrap } else if (groups instanceof DataSet || groups instanceof DataView) { this.groupsData = groups; } else { - throw new TypeError("Data must be an instance of DataSet or DataView"); + throw new TypeError('Data must be an instance of DataSet or DataView'); } if (this.groupsData) { @@ -12955,7 +12871,7 @@ return /******/ (function(modules) { // webpackBootstrap // update the order of all items in each group this._order(); - this.body.emitter.emit("change", { queue: true }); + this.body.emitter.emit('change', { queue: true }); }; /** @@ -12993,10 +12909,9 @@ return /******/ (function(modules) { // webpackBootstrap * @private */ ItemSet.prototype._getType = function (itemData) { - return itemData.type || this.options.type || (itemData.end ? "range" : "box"); + return itemData.type || this.options.type || (itemData.end ? 'range' : 'box'); }; - /** * Get the group id for an item * @param {Object} itemData @@ -13005,7 +12920,7 @@ return /******/ (function(modules) { // webpackBootstrap */ ItemSet.prototype._getGroupId = function (itemData) { var type = this._getType(itemData); - if (type == "background" && itemData.group == undefined) { + if (type == 'background' && itemData.group == undefined) { return BACKGROUND; } else { return this.groupsData ? itemData.group : UNGROUPED; @@ -13044,18 +12959,18 @@ return /******/ (function(modules) { // webpackBootstrap 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") { + } 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;}"); + 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 + "\""); + throw new TypeError('Unknown item type "' + type + '"'); } } }); this._order(); this.stackDirty = true; // force re-stacking of all items next redraw - this.body.emitter.emit("change", { queue: true }); + this.body.emitter.emit('change', { queue: true }); }; /** @@ -13085,7 +13000,7 @@ return /******/ (function(modules) { // webpackBootstrap // update order this._order(); this.stackDirty = true; // force re-stacking of all items next redraw - this.body.emitter.emit("change", { queue: true }); + this.body.emitter.emit('change', { queue: true }); } }; @@ -13125,7 +13040,7 @@ return /******/ (function(modules) { // webpackBootstrap if (!group) { // check for reserved ids if (id == UNGROUPED || id == BACKGROUND) { - throw new Error("Illegal group id. " + id + " is a reserved id."); + throw new Error('Illegal group id. ' + id + ' is a reserved id.'); } var groupOptions = Object.create(me.options); @@ -13154,7 +13069,7 @@ return /******/ (function(modules) { // webpackBootstrap } }); - this.body.emitter.emit("change", { queue: true }); + this.body.emitter.emit('change', { queue: true }); }; /** @@ -13175,7 +13090,7 @@ return /******/ (function(modules) { // webpackBootstrap this.markDirty(); - this.body.emitter.emit("change", { queue: true }); + this.body.emitter.emit('change', { queue: true }); }; /** @@ -13333,7 +13248,7 @@ return /******/ (function(modules) { // webpackBootstrap props.start = item.data.start.valueOf(); } if (me.options.editable.updateGroup) { - if ("group" in item.data) props.group = item.data.group; + if ('group' in item.data) props.group = item.data.group; } this.touchParams.itemProps = [props]; @@ -13347,7 +13262,7 @@ return /******/ (function(modules) { // webpackBootstrap props.end = item.data.end.valueOf(); } if (me.options.editable.updateGroup) { - if ("group" in item.data) props.group = item.data.group; + if ('group' in item.data) props.group = item.data.group; } this.touchParams.itemProps = [props]; @@ -13360,10 +13275,10 @@ return /******/ (function(modules) { // webpackBootstrap }; if (me.options.editable.updateTime) { - if ("start" in item.data) { + if ('start' in item.data) { props.start = item.data.start.valueOf(); - if ("end" in item.data) { + 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; @@ -13371,7 +13286,7 @@ return /******/ (function(modules) { // webpackBootstrap } } if (me.options.editable.updateGroup) { - if ("group" in item.data) props.group = item.data.group; + if ('group' in item.data) props.group = item.data.group; } return props; @@ -13402,19 +13317,19 @@ return /******/ (function(modules) { // webpackBootstrap var initial = me.body.util.toTime(props.initialX - xOffset); var offset = current - initial; - if ("start" in props) { + if ('start' in props) { var start = new Date(props.start + offset); newProps.start = snap ? snap(start, scale, step) : start; } - if ("end" in props) { + if ('end' in props) { var end = new Date(props.end + offset); newProps.end = snap ? snap(end, scale, step) : end; - } else if ("duration" in props) { + } else if ('duration' in props) { newProps.end = new Date(newProps.start.valueOf() + props.duration); } - if ("group" in props) { + if ('group' in props) { // drag from one group to another var group = me.groupFromTarget(event); newProps.group = group && group.groupId; @@ -13430,7 +13345,7 @@ return /******/ (function(modules) { // webpackBootstrap }); this.stackDirty = true; // force re-stacking of all items next redraw - this.body.emitter.emit("change"); + this.body.emitter.emit('change'); event.stopPropagation(); } @@ -13444,15 +13359,15 @@ return /******/ (function(modules) { // webpackBootstrap */ ItemSet.prototype._updateItemProps = function (item, props) { // TODO: copy all properties from props to item? (also new ones) - if ("start" in props) { + if ('start' in props) { item.data.start = props.start; } - if ("end" in props) { + if ('end' in props) { item.data.end = props.end; - } else if ("duration" in props) { + } else if ('duration' in props) { item.data.end = new Date(props.start.valueOf() + props.duration); } - if ("group" in props && item.data.group != props.group) { + if ('group' in props && item.data.group != props.group) { this._moveToGroup(item, props.group); } }; @@ -13495,15 +13410,15 @@ return /******/ (function(modules) { // webpackBootstrap itemData = me.itemsData.get(id, me.itemOptions); var changed = false; - if ("start" in props.item.data) { + 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"); + itemData.start = util.convert(props.item.data.start, dataset._options.type && dataset._options.type.start || 'Date'); } - if ("end" in props.item.data) { + 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"); + itemData.end = util.convert(props.item.data.end, dataset._options.type && dataset._options.type.end || 'Date'); } - if ("group" in props.item.data) { + if ('group' in props.item.data) { changed = changed || props.group != props.item.data.group; itemData.group = props.item.data.group; } @@ -13520,7 +13435,7 @@ return /******/ (function(modules) { // webpackBootstrap me._updateItemProps(props.item, props); me.stackDirty = true; // force re-stacking of all items next redraw - me.body.emitter.emit("change"); + me.body.emitter.emit('change'); } }); } @@ -13561,7 +13476,7 @@ return /******/ (function(modules) { // webpackBootstrap // 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", { + this.body.emitter.emit('select', { items: newSelection }); } @@ -13600,11 +13515,11 @@ return /******/ (function(modules) { // webpackBootstrap var newItem = { start: snap ? snap(start, scale, step) : start, - content: "new item" + content: 'new item' }; // when default type is a range, add a default end date to the new item - if (this.options.type === "range") { + if (this.options.type === 'range') { var end = this.body.util.toTime(x + this.props.width / 5); newItem.end = snap ? snap(end, scale, step) : end; } @@ -13676,7 +13591,7 @@ return /******/ (function(modules) { // webpackBootstrap this.setSelection(selection); - this.body.emitter.emit("select", { + this.body.emitter.emit('select', { items: this.getSelection() }); } @@ -13723,8 +13638,8 @@ return /******/ (function(modules) { // webpackBootstrap ItemSet.itemFromTarget = function (event) { var target = event.target; while (target) { - if (target.hasOwnProperty("timeline-item")) { - return target["timeline-item"]; + if (target.hasOwnProperty('timeline-item')) { + return target['timeline-item']; } target = target.parentNode; } @@ -13759,7 +13674,7 @@ return /******/ (function(modules) { // webpackBootstrap return group; } - if (this.options.orientation === "top") { + if (this.options.orientation === 'top') { if (i === this.groupIds.length - 1 && clientY > top) { return group; } @@ -13782,8 +13697,8 @@ return /******/ (function(modules) { // webpackBootstrap ItemSet.itemSetFromTarget = function (event) { var target = event.target; while (target) { - if (target.hasOwnProperty("timeline-itemset")) { - return target["timeline-itemset"]; + if (target.hasOwnProperty('timeline-itemset')) { + return target['timeline-itemset']; } target = target.parentNode; } @@ -13797,7 +13712,7 @@ return /******/ (function(modules) { // webpackBootstrap /* 33 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; var util = __webpack_require__(1); var DOMutil = __webpack_require__(2); @@ -13815,11 +13730,11 @@ return /******/ (function(modules) { // webpackBootstrap iconSpacing: 6, left: { visible: true, - position: "top-left" // top/bottom - left,center,right + position: 'top-left' // top/bottom - left,center,right }, right: { visible: true, - position: "top-left" // top/bottom - left,center,right + position: 'top-left' // top/bottom - left,center,right } }; this.side = side; @@ -13843,6 +13758,7 @@ return /******/ (function(modules) { // webpackBootstrap }; Legend.prototype.addGroup = function (label, graphOptions) { + if (!this.groups.hasOwnProperty(label)) { this.groups[label] = graphOptions; } @@ -13861,22 +13777,22 @@ return /******/ (function(modules) { // webpackBootstrap }; Legend.prototype._create = function () { - this.dom.frame = document.createElement("div"); - this.dom.frame.className = "legend"; - this.dom.frame.style.position = "absolute"; - this.dom.frame.style.top = "10px"; - this.dom.frame.style.display = "block"; - - this.dom.textArea = document.createElement("div"); - this.dom.textArea.className = "legendText"; - this.dom.textArea.style.position = "relative"; - this.dom.textArea.style.top = "0px"; - - this.svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); - this.svg.style.position = "absolute"; - this.svg.style.top = 0 + "px"; - this.svg.style.width = this.options.iconSize + 5 + "px"; - this.svg.style.height = "100%"; + this.dom.frame = document.createElement('div'); + this.dom.frame.className = 'legend'; + this.dom.frame.style.position = 'absolute'; + this.dom.frame.style.top = '10px'; + this.dom.frame.style.display = 'block'; + + this.dom.textArea = document.createElement('div'); + this.dom.textArea.className = 'legendText'; + this.dom.textArea.style.position = 'relative'; + this.dom.textArea.style.top = '0px'; + + this.svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + this.svg.style.position = 'absolute'; + this.svg.style.top = 0 + 'px'; + this.svg.style.width = this.options.iconSize + 5 + 'px'; + this.svg.style.height = '100%'; this.dom.frame.appendChild(this.svg); this.dom.frame.appendChild(this.dom.textArea); @@ -13904,7 +13820,7 @@ return /******/ (function(modules) { // webpackBootstrap }; Legend.prototype.setOptions = function (options) { - var fields = ["enabled", "orientation", "icons", "left", "right"]; + var fields = ['enabled', 'orientation', 'icons', 'left', 'right']; util.selectiveDeepExtend(fields, this.options, options); }; @@ -13922,53 +13838,53 @@ return /******/ (function(modules) { // webpackBootstrap this.hide(); } else { this.show(); - if (this.options[this.side].position == "top-left" || this.options[this.side].position == "bottom-left") { - this.dom.frame.style.left = "4px"; - this.dom.frame.style.textAlign = "left"; - this.dom.textArea.style.textAlign = "left"; - this.dom.textArea.style.left = this.options.iconSize + 15 + "px"; - this.dom.textArea.style.right = ""; - this.svg.style.left = 0 + "px"; - this.svg.style.right = ""; + if (this.options[this.side].position == 'top-left' || this.options[this.side].position == 'bottom-left') { + this.dom.frame.style.left = '4px'; + this.dom.frame.style.textAlign = 'left'; + this.dom.textArea.style.textAlign = 'left'; + this.dom.textArea.style.left = this.options.iconSize + 15 + 'px'; + this.dom.textArea.style.right = ''; + this.svg.style.left = 0 + 'px'; + this.svg.style.right = ''; } else { - this.dom.frame.style.right = "4px"; - this.dom.frame.style.textAlign = "right"; - this.dom.textArea.style.textAlign = "right"; - this.dom.textArea.style.right = this.options.iconSize + 15 + "px"; - this.dom.textArea.style.left = ""; - this.svg.style.right = 0 + "px"; - this.svg.style.left = ""; - } - - if (this.options[this.side].position == "top-left" || this.options[this.side].position == "top-right") { - this.dom.frame.style.top = 4 - Number(this.body.dom.center.style.top.replace("px", "")) + "px"; - this.dom.frame.style.bottom = ""; + this.dom.frame.style.right = '4px'; + this.dom.frame.style.textAlign = 'right'; + this.dom.textArea.style.textAlign = 'right'; + this.dom.textArea.style.right = this.options.iconSize + 15 + 'px'; + this.dom.textArea.style.left = ''; + this.svg.style.right = 0 + 'px'; + this.svg.style.left = ''; + } + + if (this.options[this.side].position == 'top-left' || this.options[this.side].position == 'top-right') { + this.dom.frame.style.top = 4 - Number(this.body.dom.center.style.top.replace('px', '')) + 'px'; + this.dom.frame.style.bottom = ''; } else { 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 = ""; + this.dom.frame.style.bottom = 4 + scrollableHeight + Number(this.body.dom.center.style.top.replace('px', '')) + 'px'; + this.dom.frame.style.top = ''; } if (this.options.icons == false) { - this.dom.frame.style.width = this.dom.textArea.offsetWidth + 10 + "px"; - this.dom.textArea.style.right = ""; - this.dom.textArea.style.left = ""; - this.svg.style.width = "0px"; + 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.dom.frame.style.width = this.options.iconSize + 15 + this.dom.textArea.offsetWidth + 10 + 'px'; this.drawLegendIcons(); } - var content = ""; + 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 + "
"; + content += this.groups[groupId].content + '
'; } } } this.dom.textArea.innerHTML = content; - this.dom.textArea.style.lineHeight = 0.75 * this.options.iconSize + this.options.iconSpacing + "px"; + this.dom.textArea.style.lineHeight = 0.75 * this.options.iconSize + this.options.iconSpacing + 'px'; } }; @@ -13976,13 +13892,13 @@ return /******/ (function(modules) { // webpackBootstrap if (this.dom.frame.parentNode) { DOMutil.prepareElements(this.svgElements); var padding = window.getComputedStyle(this.dom.frame).paddingTop; - var iconOffset = Number(padding.replace("px", "")); + 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"; + this.svg.style.width = iconWidth + 5 + iconOffset + 'px'; for (var groupId in this.groups) { if (this.groups.hasOwnProperty(groupId)) { @@ -14003,7 +13919,7 @@ return /******/ (function(modules) { // webpackBootstrap /* 34 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; var util = __webpack_require__(1); var DOMutil = __webpack_require__(2); @@ -14013,9 +13929,9 @@ return /******/ (function(modules) { // webpackBootstrap var DataAxis = __webpack_require__(28); var GraphGroup = __webpack_require__(29); var Legend = __webpack_require__(33); - var BarGraphFunctions = __webpack_require__(46); + var BarGraphFunctions = __webpack_require__(47); - var UNGROUPED = "__ungrouped__"; // reserved group id for ungrouped items + var UNGROUPED = '__ungrouped__'; // reserved group id for ungrouped items /** * This is the constructor of the LineGraph. It requires a Timeline body and options. @@ -14029,36 +13945,36 @@ return /******/ (function(modules) { // webpackBootstrap this.body = body; this.defaultOptions = { - yAxisOrientation: "left", - defaultGroup: "default", + yAxisOrientation: 'left', + defaultGroup: 'default', sort: true, sampling: true, - graphHeight: "400px", + graphHeight: '400px', shaded: { enabled: false, - orientation: "bottom" // top, bottom + orientation: 'bottom' // top, bottom }, - style: "line", // line, bar + style: 'line', // line, bar barChart: { width: 50, - handleOverlap: "overlap", - align: "center" // left, center, right + handleOverlap: 'overlap', + align: 'center' // left, center, right }, catmullRom: { enabled: true, - parametrization: "centripetal", // uniform (alpha = 0.0), chordal (alpha = 1.0), centripetal (alpha = 0.5) + 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 + style: 'square' // square, circle }, dataAxis: { showMinorLabels: true, showMajorLabels: true, icons: false, - width: "40px", + width: '40px', visible: true, alignZeros: true, customRange: { @@ -14086,11 +14002,11 @@ return /******/ (function(modules) { // webpackBootstrap icons: true, left: { visible: true, - position: "top-left" // top/bottom - left,right + position: 'top-left' // top/bottom - left,right }, right: { visible: true, - position: "top-right" // top/bottom - left,right + position: 'top-right' // top/bottom - left,right } }, groups: { @@ -14114,26 +14030,26 @@ return /******/ (function(modules) { // webpackBootstrap // listeners for the DataSet of the items this.itemListeners = { - add: function (event, params, senderId) { + add: function add(event, params, senderId) { me._onAdd(params.items); }, - update: function (event, params, senderId) { + update: function update(event, params, senderId) { me._onUpdate(params.items); }, - remove: function (event, params, senderId) { + remove: function remove(event, params, senderId) { me._onRemove(params.items); } }; // listeners for the DataSet of the groups this.groupListeners = { - add: function (event, params, senderId) { + add: function add(event, params, senderId) { me._onAddGroups(params.items); }, - update: function (event, params, senderId) { + update: function update(event, params, senderId) { me._onUpdateGroups(params.items); }, - remove: function (event, params, senderId) { + remove: function remove(event, params, senderId) { me._onRemoveGroups(params.items); } }; @@ -14147,7 +14063,7 @@ return /******/ (function(modules) { // webpackBootstrap this.setOptions(options); this.groupsUsingDefaultStyles = [0]; this.COUNTER = 0; - this.body.emitter.on("rangechanged", function () { + 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); @@ -14156,7 +14072,7 @@ return /******/ (function(modules) { // webpackBootstrap // 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.body.emitter.emit('change'); } LineGraph.prototype = new Component(); @@ -14165,28 +14081,28 @@ return /******/ (function(modules) { // webpackBootstrap * Create the HTML DOM for the ItemSet */ LineGraph.prototype._create = function () { - var frame = document.createElement("div"); - frame.className = "LineGraph"; + 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"; + 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.options.dataAxis.orientation = 'left'; this.yAxisLeft = new DataAxis(this.body, this.options.dataAxis, this.svg, this.options.groups); - this.options.dataAxis.orientation = "right"; + this.options.dataAxis.orientation = 'right'; this.yAxisRight = new DataAxis(this.body, this.options.dataAxis, this.svg, this.options.groups); delete this.options.dataAxis.orientation; // 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.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.show(); }; @@ -14197,30 +14113,30 @@ return /******/ (function(modules) { // webpackBootstrap */ LineGraph.prototype.setOptions = function (options) { if (options) { - var fields = ["sampling", "defaultGroup", "height", "graphHeight", "yAxisOrientation", "style", "barChart", "dataAxis", "sort", "groups"]; + 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) { + 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"); + util.mergeOptions(this.options, options, 'catmullRom'); + util.mergeOptions(this.options, options, 'drawPoints'); + util.mergeOptions(this.options, options, 'shaded'); + util.mergeOptions(this.options, options, 'legend'); if (options.catmullRom) { - if (typeof options.catmullRom == "object") { + if (typeof options.catmullRom == 'object') { if (options.catmullRom.parametrization) { - if (options.catmullRom.parametrization == "uniform") { + if (options.catmullRom.parametrization == 'uniform') { this.options.catmullRom.alpha = 0; - } else if (options.catmullRom.parametrization == "chordal") { + } else if (options.catmullRom.parametrization == 'chordal') { this.options.catmullRom.alpha = 1; } else { - this.options.catmullRom.parametrization = "centripetal"; + this.options.catmullRom.parametrization = 'centripetal'; this.options.catmullRom.alpha = 0.5; } } @@ -14262,7 +14178,6 @@ return /******/ (function(modules) { // webpackBootstrap } }; - /** * Show the component in the DOM (when not already visible). * @return {Boolean} changed @@ -14274,7 +14189,6 @@ return /******/ (function(modules) { // webpackBootstrap } }; - /** * Set items * @param {vis.DataSet | null} items @@ -14290,7 +14204,7 @@ return /******/ (function(modules) { // webpackBootstrap } else if (items instanceof DataSet || items instanceof DataView) { this.itemsData = items; } else { - throw new TypeError("Data must be an instance of DataSet or DataView"); + throw new TypeError('Data must be an instance of DataSet or DataView'); } if (oldItemsData) { @@ -14320,7 +14234,6 @@ return /******/ (function(modules) { // webpackBootstrap this.redraw(true); }; - /** * Set groups * @param {vis.DataSet} groups @@ -14347,7 +14260,7 @@ return /******/ (function(modules) { // webpackBootstrap } else if (groups instanceof DataSet || groups instanceof DataView) { this.groupsData = groups; } else { - throw new TypeError("Data must be an instance of DataSet or DataView"); + throw new TypeError('Data must be an instance of DataSet or DataView'); } if (this.groupsData) { @@ -14364,7 +14277,6 @@ return /******/ (function(modules) { // webpackBootstrap this._onUpdate(); }; - /** * Update the data * @param [ids] @@ -14395,7 +14307,6 @@ return /******/ (function(modules) { // webpackBootstrap this._onUpdateGroups(groupIds); }; - /** * this cleans the group out off the legends and the dataaxis, updates the ungrouped and updates the graph * @param {Array} groupIds @@ -14404,7 +14315,7 @@ return /******/ (function(modules) { // webpackBootstrap 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") { + if (this.groups[groupIds[i]].options.yAxisOrientation == 'right') { this.yAxisRight.removeGroup(groupIds[i]); this.legendRight.removeGroup(groupIds[i]); this.legendRight.redraw(); @@ -14421,7 +14332,6 @@ return /******/ (function(modules) { // webpackBootstrap this.redraw(true); }; - /** * update a group object with the group dataset entree * @@ -14432,7 +14342,7 @@ return /******/ (function(modules) { // webpackBootstrap 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") { + if (this.groups[groupId].options.yAxisOrientation == 'right') { this.yAxisRight.addGroup(groupId, this.groups[groupId]); this.legendRight.addGroup(groupId, this.groups[groupId]); } else { @@ -14441,7 +14351,7 @@ return /******/ (function(modules) { // webpackBootstrap } } else { this.groups[groupId].update(group); - if (this.groups[groupId].options.yAxisOrientation == "right") { + if (this.groups[groupId].options.yAxisOrientation == 'right') { this.yAxisRight.updateGroup(groupId, this.groups[groupId]); this.legendRight.updateGroup(groupId, this.groups[groupId]); } else { @@ -14453,7 +14363,6 @@ return /******/ (function(modules) { // webpackBootstrap this.legendRight.redraw(); }; - /** * this updates all groups, it is used when there is an update the the itemset. * @@ -14472,9 +14381,9 @@ return /******/ (function(modules) { // webpackBootstrap 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."); + 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"); + item.x = util.convert(item.x, 'Date'); groupsContent[item.group].push(item); } } @@ -14486,7 +14395,6 @@ return /******/ (function(modules) { // webpackBootstrap } }; - /** * 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'. @@ -14499,7 +14407,7 @@ return /******/ (function(modules) { // webpackBootstrap if (this.itemsData._data.hasOwnProperty(itemId)) { var item = this.itemsData._data[itemId]; if (item != undefined) { - if (item.hasOwnProperty("group")) { + if (item.hasOwnProperty('group')) { if (item.group === undefined) { item.group = UNGROUPED; } @@ -14533,7 +14441,6 @@ return /******/ (function(modules) { // webpackBootstrap this.legendRight.redraw(); }; - /** * Redraw the component, mandatory function * @return {boolean} Returns true if the component is resized @@ -14558,7 +14465,6 @@ return /******/ (function(modules) { // webpackBootstrap var zoomed = visibleInterval != this.lastVisibleInterval; this.lastVisibleInterval = visibleInterval; - // 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) { @@ -14566,20 +14472,20 @@ return /******/ (function(modules) { // webpackBootstrap this.svg.style.left = util.option.asSize(-this.props.width); // if the height of the graph is set as proportional, change the height of the svg - if ((this.options.height + "").indexOf("%") != -1 || this.updateSVGheightOnResize == true) { + if ((this.options.height + '').indexOf('%') != -1 || this.updateSVGheightOnResize == true) { this.updateSVGheight = true; } } // 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"; + 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"; + this.svg.style.height = ('' + this.options.graphHeight).replace('px', '') + 'px'; } // zoomed is here to ensure that animations are shown correctly. @@ -14593,7 +14499,7 @@ return /******/ (function(modules) { // webpackBootstrap 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.svg.style.left = -this.props.width - xOffset + 'px'; } } } @@ -14603,7 +14509,6 @@ return /******/ (function(modules) { // webpackBootstrap return resized; }; - /** * Update and redraw the graph. * @@ -14655,11 +14560,11 @@ return /******/ (function(modules) { // webpackBootstrap DOMutil.cleanupElements(this.svgElements); this.abortedGraphUpdate = true; this.COUNTER++; - this.body.emitter.emit("change"); + 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."); + console.log('WARNING: there may be an infinite loop in the _updateGraph emitter cycle.'); } this.COUNTER = 0; this.abortedGraphUpdate = false; @@ -14673,7 +14578,7 @@ return /******/ (function(modules) { // webpackBootstrap // draw the groups for (i = 0; i < groupIds.length; i++) { group = this.groups[groupIds[i]]; - if (group.options.style != "bar") { + if (group.options.style != 'bar') { // bar needs to be drawn enmasse group.draw(processedGroupData[groupIds[i]], group, this.framework); } @@ -14688,7 +14593,6 @@ return /******/ (function(modules) { // webpackBootstrap return false; }; - /** * first select and preprocess the data from the datasets. * the groups have their preselection of data, we now loop over this data to see @@ -14711,7 +14615,7 @@ return /******/ (function(modules) { // webpackBootstrap 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")); + 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) { @@ -14737,7 +14641,6 @@ return /******/ (function(modules) { // webpackBootstrap } }; - /** * * @param groupIds @@ -14772,7 +14675,6 @@ return /******/ (function(modules) { // webpackBootstrap } }; - /** * * @@ -14793,8 +14695,8 @@ return /******/ (function(modules) { // webpackBootstrap 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") { + 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)); @@ -14806,12 +14708,11 @@ return /******/ (function(modules) { // webpackBootstrap } // 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"); + BarGraphFunctions.getStackedBarYRange(barCombinedDataLeft, groupRanges, groupIds, '__barchartLeft', 'left'); + BarGraphFunctions.getStackedBarYRange(barCombinedDataRight, groupRanges, groupIds, '__barchartRight', 'right'); } }; - /** * this sets the Y ranges for the Y axis. It also determines which of the axis should be shown or hidden. * @param {Array} groupIds @@ -14833,7 +14734,7 @@ return /******/ (function(modules) { // webpackBootstrap // 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") { + if (group && group.options.yAxisOrientation != 'right') { yAxisLeftUsed = true; minLeft = 0; maxLeft = 0; @@ -14851,7 +14752,7 @@ return /******/ (function(modules) { // webpackBootstrap minVal = groupRanges[groupIds[i]].min; maxVal = groupRanges[groupIds[i]].max; - if (groupRanges[groupIds[i]].yAxisOrientation != "right") { + if (groupRanges[groupIds[i]].yAxisOrientation != 'right') { yAxisLeftUsed = true; minLeft = minLeft > minVal ? minVal : minLeft; maxLeft = maxLeft < maxVal ? maxVal : maxLeft; @@ -14898,17 +14799,16 @@ return /******/ (function(modules) { // webpackBootstrap } // clean the accumulated lists - if (groupIds.indexOf("__barchartLeft") != -1) { - groupIds.splice(groupIds.indexOf("__barchartLeft"), 1); + if (groupIds.indexOf('__barchartLeft') != -1) { + groupIds.splice(groupIds.indexOf('__barchartLeft'), 1); } - if (groupIds.indexOf("__barchartRight") != -1) { - groupIds.splice(groupIds.indexOf("__barchartRight"), 1); + if (groupIds.indexOf('__barchartRight') != -1) { + groupIds.splice(groupIds.indexOf('__barchartRight'), 1); } return resized; }; - /** * This shows or hides the Y axis if needed. If there is a change, the changed event is emitted by the updateYAxis function * @@ -14933,7 +14833,6 @@ return /******/ (function(modules) { // webpackBootstrap 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 @@ -14957,7 +14856,6 @@ return /******/ (function(modules) { // webpackBootstrap return extractedData; }; - /** * 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 @@ -14973,8 +14871,8 @@ return /******/ (function(modules) { // webpackBootstrap 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") { + var svgHeight = Number(this.svg.style.height.replace('px', '')); + if (group.options.yAxisOrientation == 'right') { axis = this.yAxisRight; } @@ -14997,14 +14895,13 @@ return /******/ (function(modules) { // webpackBootstrap return extractedData; }; - module.exports = LineGraph; /***/ }, /* 35 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; var util = __webpack_require__(1); var Component = __webpack_require__(25); @@ -15042,7 +14939,7 @@ return /******/ (function(modules) { // webpackBootstrap }; this.defaultOptions = { - orientation: "bottom", // supported: 'top', 'bottom' + orientation: 'bottom', // supported: 'top', 'bottom' // TODO: implement timeaxis orientations 'left' and 'right' showMinorLabels: true, showMajorLabels: true, @@ -15072,12 +14969,12 @@ return /******/ (function(modules) { // webpackBootstrap TimeAxis.prototype.setOptions = function (options) { if (options) { // copy all options that we know - util.selectiveExtend(["orientation", "showMinorLabels", "showMajorLabels", "hiddenDates", "format", "timeAxis"], this.options, options); + 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") { + if ('locale' in options) { + if (typeof moment.locale === 'function') { // moment.js 2.8.1+ moment.locale(options.locale); } else { @@ -15091,11 +14988,11 @@ return /******/ (function(modules) { // webpackBootstrap * Create the HTML DOM for the TimeAxis */ TimeAxis.prototype._create = function () { - this.dom.foreground = document.createElement("div"); - this.dom.background = document.createElement("div"); + this.dom.foreground = document.createElement('div'); + this.dom.background = document.createElement('div'); - this.dom.foreground.className = "timeaxis foreground"; - this.dom.background.className = "timeaxis background"; + this.dom.foreground.className = 'timeaxis foreground'; + this.dom.background.className = 'timeaxis background'; }; /** @@ -15124,7 +15021,7 @@ return /******/ (function(modules) { // webpackBootstrap var background = this.dom.background; // determine the correct parent DOM element (depending on option orientation) - var parent = options.orientation == "top" ? this.body.dom.top : this.body.dom.bottom; + var parent = options.orientation == 'top' ? this.body.dom.top : this.body.dom.bottom; var parentChanged = foreground.parentNode !== parent; // calculate character width and height @@ -15141,7 +15038,7 @@ return /******/ (function(modules) { // webpackBootstrap props.height = props.minorLabelHeight + props.majorLabelHeight; props.width = foreground.offsetWidth; - props.minorLineHeight = this.body.domProps.root.height - props.majorLabelHeight - (options.orientation == "top" ? this.body.domProps.bottom.height : this.body.domProps.top.height); + props.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 @@ -15152,7 +15049,7 @@ return /******/ (function(modules) { // webpackBootstrap foreground.parentNode && foreground.parentNode.removeChild(foreground); background.parentNode && background.parentNode.removeChild(background); - foreground.style.height = this.props.height + "px"; + foreground.style.height = this.props.height + 'px'; this._repaintLabels(); @@ -15179,8 +15076,8 @@ return /******/ (function(modules) { // webpackBootstrap 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 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(); @@ -15227,7 +15124,7 @@ return /******/ (function(modules) { // webpackBootstrap x = this.body.util.toScreen(cur); width = x - xPrev; if (prevLine) { - prevLine.style.width = width + "px"; + prevLine.style.width = width + 'px'; } if (this.options.showMinorLabels) { @@ -15285,8 +15182,8 @@ return /******/ (function(modules) { // webpackBootstrap if (!label) { // create new label - var content = document.createTextNode(""); - label = document.createElement("div"); + var content = document.createTextNode(''); + label = document.createElement('div'); label.appendChild(content); this.dom.foreground.appendChild(label); } @@ -15294,9 +15191,9 @@ return /******/ (function(modules) { // webpackBootstrap 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.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 }; @@ -15315,18 +15212,18 @@ return /******/ (function(modules) { // webpackBootstrap if (!label) { // create label var content = document.createTextNode(text); - label = document.createElement("div"); + 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.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"; + label.style.top = orientation == 'top' ? '0' : this.props.minorLabelHeight + 'px'; + label.style.left = x + 'px'; }; /** @@ -15342,21 +15239,21 @@ return /******/ (function(modules) { // webpackBootstrap var line = this.dom.redundant.lines.shift(); if (!line) { // create vertical line - line = document.createElement("div"); + line = document.createElement('div'); this.dom.background.appendChild(line); } this.dom.lines.push(line); var props = this.props; - if (orientation == "top") { - line.style.top = props.majorLabelHeight + "px"; + if (orientation == 'top') { + line.style.top = props.majorLabelHeight + 'px'; } else { - line.style.top = this.body.domProps.top.height + "px"; + line.style.top = this.body.domProps.top.height + 'px'; } - line.style.height = props.minorLineHeight + "px"; - line.style.left = x - props.minorLineWidth / 2 + "px"; + line.style.height = props.minorLineHeight + 'px'; + line.style.left = x - props.minorLineWidth / 2 + 'px'; - line.className = "grid vertical minor " + className; + line.className = 'grid vertical minor ' + className; return line; }; @@ -15374,21 +15271,21 @@ return /******/ (function(modules) { // webpackBootstrap var line = this.dom.redundant.lines.shift(); if (!line) { // create vertical line - line = document.createElement("div"); + line = document.createElement('div'); this.dom.background.appendChild(line); } this.dom.lines.push(line); var props = this.props; - if (orientation == "top") { - line.style.top = "0"; + if (orientation == 'top') { + line.style.top = '0'; } else { - line.style.top = this.body.domProps.top.height + "px"; + line.style.top = this.body.domProps.top.height + 'px'; } - line.style.left = x - props.majorLineWidth / 2 + "px"; - line.style.height = props.majorLineHeight + "px"; + line.style.left = x - props.majorLineWidth / 2 + 'px'; + line.style.height = props.majorLineHeight + 'px'; - line.className = "grid vertical major " + className; + line.className = 'grid vertical major ' + className; return line; }; @@ -15404,11 +15301,11 @@ return /******/ (function(modules) { // webpackBootstrap // determine the char width and height on the minor axis if (!this.dom.measureCharMinor) { - this.dom.measureCharMinor = document.createElement("DIV"); - this.dom.measureCharMinor.className = "text minor measure"; - this.dom.measureCharMinor.style.position = "absolute"; + this.dom.measureCharMinor = 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.measureCharMinor.appendChild(document.createTextNode('0')); this.dom.foreground.appendChild(this.dom.measureCharMinor); } this.props.minorCharHeight = this.dom.measureCharMinor.clientHeight; @@ -15416,11 +15313,11 @@ return /******/ (function(modules) { // webpackBootstrap // 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 = 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.measureCharMajor.appendChild(document.createTextNode('0')); this.dom.foreground.appendChild(this.dom.measureCharMajor); } this.props.majorCharHeight = this.dom.measureCharMajor.clientHeight; @@ -15433,48 +15330,74 @@ return /******/ (function(modules) { // webpackBootstrap /* 36 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; - var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; - // Load custom shapes into CanvasRenderingContext2D - __webpack_require__(48); + var _Groups = __webpack_require__(49); - var Emitter = __webpack_require__(42); - var Hammer = __webpack_require__(41); - var util = __webpack_require__(1); - var DataSet = __webpack_require__(3); - var DataView = __webpack_require__(4); - var dotparser = __webpack_require__(38); - var gephiParser = __webpack_require__(39); - var Images = __webpack_require__(37); - var Activator = __webpack_require__(49); + var _Groups2 = _interopRequireWildcard(_Groups); + + var _NodesHandler = __webpack_require__(50); + + var _NodesHandler2 = _interopRequireWildcard(_NodesHandler); + + var _EdgesHandler = __webpack_require__(51); + + var _EdgesHandler2 = _interopRequireWildcard(_EdgesHandler); + + var _PhysicsEngine = __webpack_require__(52); + + var _PhysicsEngine2 = _interopRequireWildcard(_PhysicsEngine); - var Groups = _interopRequire(__webpack_require__(50)); + var _ClusterEngine = __webpack_require__(53); - var NodesHandler = _interopRequire(__webpack_require__(!(function webpackMissingModule() { var e = new Error("Cannot find module \"./modules/NodesHandler\""); e.code = 'MODULE_NOT_FOUND'; throw e; }()))); + var _ClusterEngine2 = _interopRequireWildcard(_ClusterEngine); - var EdgesHandler = _interopRequire(__webpack_require__(!(function webpackMissingModule() { var e = new Error("Cannot find module \"./modules/EdgesHandler\""); e.code = 'MODULE_NOT_FOUND'; throw e; }()))); + var _CanvasRenderer = __webpack_require__(54); - var PhysicsEngine = _interopRequire(__webpack_require__(53)); + var _CanvasRenderer2 = _interopRequireWildcard(_CanvasRenderer); - var ClusterEngine = _interopRequire(__webpack_require__(54)); + var _Canvas = __webpack_require__(55); - var CanvasRenderer = _interopRequire(__webpack_require__(!(function webpackMissingModule() { var e = new Error("Cannot find module \"./modules/CanvasRenderer\""); e.code = 'MODULE_NOT_FOUND'; throw e; }()))); + var _Canvas2 = _interopRequireWildcard(_Canvas); - var Canvas = _interopRequire(__webpack_require__(56)); + var _View = __webpack_require__(56); - var View = _interopRequire(__webpack_require__(57)); + var _View2 = _interopRequireWildcard(_View); - var InteractionHandler = _interopRequire(__webpack_require__(58)); + var _InteractionHandler = __webpack_require__(57); - var SelectionHandler = _interopRequire(__webpack_require__(59)); + var _InteractionHandler2 = _interopRequireWildcard(_InteractionHandler); - var LayoutEngine = _interopRequire(__webpack_require__(60)); + var _SelectionHandler = __webpack_require__(58); - var ManipulationSystem = _interopRequire(__webpack_require__(61)); + var _SelectionHandler2 = _interopRequireWildcard(_SelectionHandler); + + var _LayoutEngine = __webpack_require__(59); + + var _LayoutEngine2 = _interopRequireWildcard(_LayoutEngine); + + var _ManipulationSystem = __webpack_require__(60); + + var _ManipulationSystem2 = _interopRequireWildcard(_ManipulationSystem); + + var _ConfigurationSystem = __webpack_require__(61); + + var _ConfigurationSystem2 = _interopRequireWildcard(_ConfigurationSystem); + + // Load custom shapes into CanvasRenderingContext2D + __webpack_require__(62); - var ConfigurationSystem = _interopRequire(__webpack_require__(62)); + var Emitter = __webpack_require__(42); + var Hammer = __webpack_require__(41); + var util = __webpack_require__(1); + var DataSet = __webpack_require__(3); + var DataView = __webpack_require__(4); + var dotparser = __webpack_require__(38); + var gephiParser = __webpack_require__(39); + var Images = __webpack_require__(37); + var Activator = __webpack_require__(63); /** * @constructor Network @@ -15489,8 +15412,9 @@ return /******/ (function(modules) { // webpackBootstrap */ function Network(container, data, options) { var _this = this; + if (!(this instanceof Network)) { - throw new SyntaxError("Constructor must be called with the new operator"); + throw new SyntaxError('Constructor must be called with the new operator'); } // set constant values @@ -15511,9 +15435,9 @@ return /******/ (function(modules) { // webpackBootstrap edges: null // A DataSet or DataView }, functions: { - createNode: function () {}, - createEdge: function () {}, - getPointer: function () {} + createNode: function createNode() {}, + createEdge: function createEdge() {}, + getPointer: function getPointer() {} }, emitter: { on: this.on.bind(this), @@ -15522,17 +15446,17 @@ return /******/ (function(modules) { // webpackBootstrap once: this.once.bind(this) }, eventListeners: { - onTap: function () {}, - onTouch: function () {}, - onDoubleTap: function () {}, - onHold: function () {}, - onDragStart: function () {}, - onDrag: function () {}, - onDragEnd: function () {}, - onMouseWheel: function () {}, - onPinch: function () {}, - onMouseMove: function () {}, - onRelease: function () {} + onTap: function onTap() {}, + onTouch: function onTouch() {}, + onDoubleTap: function onDoubleTap() {}, + onHold: function onHold() {}, + onDragStart: function onDragStart() {}, + onDrag: function onDrag() {}, + onDragEnd: function onDragEnd() {}, + onMouseWheel: function onMouseWheel() {}, + onPinch: function onPinch() {}, + onMouseMove: function onMouseMove() {}, + onRelease: function onRelease() {} }, container: container, view: { @@ -15546,26 +15470,26 @@ return /******/ (function(modules) { // webpackBootstrap // setting up all modules var images = new Images(function () { - return _this.body.emitter.emit("_requestRedraw"); + return _this.body.emitter.emit('_requestRedraw'); }); // object with images - this.groups = new Groups(); // object with groups - this.canvas = new Canvas(this.body); // DOM handler - this.selectionHandler = new SelectionHandler(this.body, this.canvas); // Selection handler - this.interactionHandler = new InteractionHandler(this.body, this.canvas, this.selectionHandler); // Interaction handler handles all the hammer bindings (that are bound by canvas), key - this.view = new View(this.body, this.canvas); // camera handler, does animations and zooms - this.renderer = new CanvasRenderer(this.body, this.canvas); // renderer, starts renderloop, has events that modules can hook into - this.physics = new PhysicsEngine(this.body); // physics engine, does all the simulations - this.layoutEngine = new LayoutEngine(this.body); // layout engine for inital layout and hierarchical layout - this.clustering = new ClusterEngine(this.body); // clustering api - this.manipulation = new ManipulationSystem(this.body, this.canvas, this.selectionHandler); // data manipulation system - - this.nodesHandler = new NodesHandler(this.body, images, this.groups, this.layoutEngine); // Handle adding, deleting and updating of nodes as well as global options - this.edgesHandler = new EdgesHandler(this.body, images, this.groups); // Handle adding, deleting and updating of edges as well as global options - - this.configurationSystem = new ConfigurationSystem(this); + this.groups = new _Groups2['default'](); // object with groups + this.canvas = new _Canvas2['default'](this.body); // DOM handler + this.selectionHandler = new _SelectionHandler2['default'](this.body, this.canvas); // Selection handler + this.interactionHandler = new _InteractionHandler2['default'](this.body, this.canvas, this.selectionHandler); // Interaction handler handles all the hammer bindings (that are bound by canvas), key + this.view = new _View2['default'](this.body, this.canvas); // camera handler, does animations and zooms + this.renderer = new _CanvasRenderer2['default'](this.body, this.canvas); // renderer, starts renderloop, has events that modules can hook into + this.physics = new _PhysicsEngine2['default'](this.body); // physics engine, does all the simulations + this.layoutEngine = new _LayoutEngine2['default'](this.body); // layout engine for inital layout and hierarchical layout + this.clustering = new _ClusterEngine2['default'](this.body); // clustering api + this.manipulation = new _ManipulationSystem2['default'](this.body, this.canvas, this.selectionHandler); // data manipulation system + + this.nodesHandler = new _NodesHandler2['default'](this.body, images, this.groups, this.layoutEngine); // Handle adding, deleting and updating of nodes as well as global options + this.edgesHandler = new _EdgesHandler2['default'](this.body, images, this.groups); // Handle adding, deleting and updating of edges as well as global options + + this.configurationSystem = new _ConfigurationSystem2['default'](this); // create the DOM elements - this.canvas.create(); + this.canvas._create(); // apply options this.setOptions(options); @@ -15577,8 +15501,6 @@ return /******/ (function(modules) { // webpackBootstrap // Extend Network with an Emitter mixin Emitter(Network.prototype); - - /** * Set options * @param {Object} options @@ -15588,7 +15510,6 @@ return /******/ (function(modules) { // webpackBootstrap // the hierarchical system can adapt the edges and the physics to it's own options because not all combinations work with the hierarichical system. options = this.layoutEngine.setOptions(options.layout, options); - // pass the options to the modules this.groups.setOptions(options.groups); this.nodesHandler.setOptions(options.nodes); @@ -15609,27 +15530,26 @@ return /******/ (function(modules) { // webpackBootstrap if (options.clickToUse === true) { if (this.activator === undefined) { this.activator = new Activator(this.frame); - this.activator.on("change", this._createKeyBinds.bind(this)); + this.activator.on('change', this._createKeyBinds.bind(this)); } } else { if (this.activator !== undefined) { this.activator.destroy(); delete this.activator; } - this.body.emitter.emit("activate"); + this.body.emitter.emit('activate'); } } else { - this.body.emitter.emit("activate"); + this.body.emitter.emit('activate'); } this.canvas.setSize(); // start the physics simulation. Can be safely called multiple times. - this.body.emitter.emit("startSimulation"); + this.body.emitter.emit('startSimulation'); } }; - /** * Update the this.body.nodeIndices with the most recent node index list * @private @@ -15658,24 +15578,25 @@ return /******/ (function(modules) { // webpackBootstrap }; Network.prototype.bindEventListeners = function () { - var _this = this; + var _this2 = this; + // this event will trigger a rebuilding of the cache everything. Used when nodes or edges have been added or removed. - this.body.emitter.on("_dataChanged", function (params) { + this.body.emitter.on('_dataChanged', function (params) { // update shortcut lists - _this._updateVisibleIndices(); - _this.physics.updatePhysicsIndices(); + _this2._updateVisibleIndices(); + _this2.physics.updatePhysicsIndices(); // call the dataUpdated event because the only difference between the two is the updating of the indices - _this.body.emitter.emit("_dataUpdated"); + _this2.body.emitter.emit('_dataUpdated'); }); // this is called when options of EXISTING nodes or edges have changed. - this.body.emitter.on("_dataUpdated", function () { + this.body.emitter.on('_dataUpdated', function () { // update values - _this._updateValueRange(_this.body.nodes); - _this._updateValueRange(_this.body.edges); + _this2._updateValueRange(_this2.body.nodes); + _this2._updateValueRange(_this2.body.edges); // start simulation (can be called safely, even if already running) - _this.body.emitter.emit("startSimulation"); + _this2.body.emitter.emit('startSimulation'); }); }; @@ -15692,14 +15613,14 @@ return /******/ (function(modules) { // webpackBootstrap */ Network.prototype.setData = function (data) { // reset the physics engine. - this.body.emitter.emit("resetPhysics"); - this.body.emitter.emit("_resetData"); + this.body.emitter.emit('resetPhysics'); + this.body.emitter.emit('_resetData'); // unselect all to ensure no selections from old data are carried over. this.selectionHandler.unselectAll(); 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."); + throw new SyntaxError('Data must contain either parameter "dot" or ' + ' parameter pair "nodes" and "edges", but not both.'); } // set options @@ -15725,13 +15646,12 @@ return /******/ (function(modules) { // webpackBootstrap } // emit change in data - this.body.emitter.emit("_dataChanged"); + this.body.emitter.emit('_dataChanged'); // find a stable position or start animating to a stable position - this.body.emitter.emit("initPhysics"); + this.body.emitter.emit('initPhysics'); }; - /** * Cleans up all bindings of the network, removing it fully from the memory IF the variable is set to null after calling this function. * var network = new vis.Network(..); @@ -15739,7 +15659,7 @@ return /******/ (function(modules) { // webpackBootstrap * network = null; */ Network.prototype.destroy = function () { - this.body.emitter.emit("destroy"); + this.body.emitter.emit('destroy'); // clear events this.body.emitter.off(); @@ -15748,8 +15668,6 @@ return /******/ (function(modules) { // webpackBootstrap util.recursiveDOMDelete(this.body.container); }; - - /** * Update the values of all object in the given array according to the current * value range of the objects in the array. @@ -15786,7 +15704,6 @@ return /******/ (function(modules) { // webpackBootstrap } }; - /** * Scale the network * @param {Number} scale Scaling factor 1.0 is unscaled @@ -15805,7 +15722,6 @@ return /******/ (function(modules) { // webpackBootstrap return this.body.view.scale; }; - /** * Load the XY positions of the nodes into the dataset. */ @@ -15855,7 +15771,6 @@ return /******/ (function(modules) { // webpackBootstrap return dataArray; }; - /** * Returns true when the Network is active. * @returns {boolean} @@ -15864,7 +15779,6 @@ return /******/ (function(modules) { // webpackBootstrap return !this.activator || this.activator.active; }; - /** * Sets the scale * @returns {Number} @@ -15873,7 +15787,6 @@ return /******/ (function(modules) { // webpackBootstrap return this._setScale(); }; - /** * Returns the scale * @returns {Number} @@ -15882,7 +15795,6 @@ return /******/ (function(modules) { // webpackBootstrap return this._getScale(); }; - /** * Check if a node is a cluster. * @param nodeId @@ -15892,7 +15804,7 @@ return /******/ (function(modules) { // webpackBootstrap if (this.body.nodes[nodeId] !== undefined) { return this.body.nodes[nodeId].isCluster; } else { - console.log("Node does not exist."); + console.log('Node does not exist.'); return false; } }; @@ -15905,7 +15817,6 @@ return /******/ (function(modules) { // webpackBootstrap return this.DOMtoCanvas({ x: 0.5 * this.frame.canvas.clientWidth, y: 0.5 * this.frame.canvas.clientHeight }); }; - Network.prototype.getBoundingBox = function (nodeId) { if (this.body.nodes[nodeId] !== undefined) { return this.body.nodes[nodeId].boundingBox; @@ -15935,7 +15846,6 @@ return /******/ (function(modules) { // webpackBootstrap return nodeList; }; - Network.prototype.getEdgesFromNode = function (nodeId) { var edgesList = []; if (this.body.nodes[nodeId] !== undefined) { @@ -15957,12 +15867,12 @@ return /******/ (function(modules) { // webpackBootstrap /* 37 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; - /** * @class Images * This class loads images and keeps them stored. */ + "use strict"; + function Images(callback) { this.images = {}; this.imageBroken = {}; @@ -16030,8 +15940,6 @@ return /******/ (function(modules) { // webpackBootstrap /* 38 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; - /** * 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. @@ -16043,6 +15951,8 @@ return /******/ (function(modules) { // webpackBootstrap * {Object[]} nodes * {Object[]} edges */ + 'use strict'; + function parseDOT(data) { dot = data; return parseGraph(); @@ -16058,22 +15968,22 @@ return /******/ (function(modules) { // webpackBootstrap // map with all delimiters var DELIMITERS = { - "{": true, - "}": true, - "[": true, - "]": true, - ";": true, - "=": true, - ",": true, + '{': true, + '}': true, + '[': true, + ']': true, + ';': true, + '=': true, + ',': true, - "->": true, - "--": true + '->': true, + '--': true }; - var dot = ""; // current dot file + 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 c = ''; // current token character in expr + var token = ''; // current token var tokenType = TOKENTYPE.NULL; // type of the token /** @@ -16148,7 +16058,7 @@ return /******/ (function(modules) { // webpackBootstrap * @param {*} value */ function setValue(obj, path, value) { - var keys = path.split("."); + var keys = path.split('.'); var o = obj; while (keys.length) { var key = keys.shift(); @@ -16268,10 +16178,10 @@ return /******/ (function(modules) { // webpackBootstrap */ function getToken() { tokenType = TOKENTYPE.NULL; - token = ""; + token = ''; // skip over whitespaces - while (c === " " || c === "\t" || c === "\n" || c === "\r") { + while (c === ' ' || c === '\t' || c === '\n' || c === '\r') { // space, tab, enter next(); } @@ -16280,31 +16190,31 @@ return /******/ (function(modules) { // webpackBootstrap var isComment = false; // skip comment - if (c === "#") { + if (c === '#') { // find the previous non-space character var i = index - 1; - while (dot.charAt(i) === " " || dot.charAt(i) === "\t") { + while (dot.charAt(i) === ' ' || dot.charAt(i) === '\t') { i--; } - if (dot.charAt(i) === "\n" || dot.charAt(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") { + while (c != '' && c != '\n') { next(); } isComment = true; } } - if (c === "/" && nextPreview() === "/") { + if (c === '/' && nextPreview() === '/') { // skip line comment - while (c != "" && c != "\n") { + while (c != '' && c != '\n') { next(); } isComment = true; } - if (c === "/" && nextPreview() === "*") { + if (c === '/' && nextPreview() === '*') { // skip block comment - while (c != "") { - if (c === "*" && nextPreview() === "/") { + while (c != '') { + if (c === '*' && nextPreview() === '/') { // end of block comment found. skip these last two characters next(); next(); @@ -16317,14 +16227,14 @@ return /******/ (function(modules) { // webpackBootstrap } // skip over whitespaces - while (c === " " || c === "\t" || c === "\n" || c === "\r") { + while (c === ' ' || c === '\t' || c === '\n' || c === '\r') { // space, tab, enter next(); } } while (isComment); // check for end of dot file - if (c === "") { + if (c === '') { // token is still empty tokenType = TOKENTYPE.DELIMITER; return; @@ -16350,7 +16260,7 @@ return /******/ (function(modules) { // webpackBootstrap // check for an identifier (number or string) // TODO: more precise parsing of numbers/strings (and the port separator ':') - if (isAlphaNumeric(c) || c === "-") { + if (isAlphaNumeric(c) || c === '-') { token += c; next(); @@ -16358,9 +16268,9 @@ return /******/ (function(modules) { // webpackBootstrap token += c; next(); } - if (token === "false") { + if (token === 'false') { token = false; // convert to boolean - } else if (token === "true") { + } else if (token === 'true') { token = true; // convert to boolean } else if (!isNaN(Number(token))) { token = Number(token); // convert to number @@ -16370,18 +16280,18 @@ return /******/ (function(modules) { // webpackBootstrap } // check for a string enclosed by double quotes - if (c === "\"") { + if (c === '"') { next(); - while (c != "" && (c != "\"" || c === "\"" && nextPreview() === "\"")) { + while (c != '' && (c != '"' || c === '"' && nextPreview() === '"')) { token += c; - if (c === "\"") { + if (c === '"') { // skip the escape character next(); } next(); } - if (c != "\"") { - throw newSyntaxError("End of string \" expected"); + if (c != '"') { + throw newSyntaxError('End of string " expected'); } next(); tokenType = TOKENTYPE.IDENTIFIER; @@ -16390,11 +16300,11 @@ return /******/ (function(modules) { // webpackBootstrap // something unknown is found, wrong characters, a syntax error tokenType = TOKENTYPE.UNKNOWN; - while (c != "") { + while (c != '') { token += c; next(); } - throw new SyntaxError("Syntax error in part \"" + chop(token, 30) + "\""); + throw new SyntaxError('Syntax error in part "' + chop(token, 30) + '"'); } /** @@ -16408,13 +16318,13 @@ return /******/ (function(modules) { // webpackBootstrap getToken(); // optional strict keyword - if (token === "strict") { + if (token === 'strict') { graph.strict = true; getToken(); } // graph or digraph keyword - if (token === "graph" || token === "digraph") { + if (token === 'graph' || token === 'digraph') { graph.type = token; getToken(); } @@ -16426,8 +16336,8 @@ return /******/ (function(modules) { // webpackBootstrap } // open angle bracket - if (token != "{") { - throw newSyntaxError("Angle bracket { expected"); + if (token != '{') { + throw newSyntaxError('Angle bracket { expected'); } getToken(); @@ -16435,14 +16345,14 @@ return /******/ (function(modules) { // webpackBootstrap parseStatements(graph); // close angle bracket - if (token != "}") { - throw newSyntaxError("Angle bracket } expected"); + if (token != '}') { + throw newSyntaxError('Angle bracket } expected'); } getToken(); // end of file - if (token !== "") { - throw newSyntaxError("End of file expected"); + if (token !== '') { + throw newSyntaxError('End of file expected'); } getToken(); @@ -16459,9 +16369,9 @@ return /******/ (function(modules) { // webpackBootstrap * @param {Object} graph */ function parseStatements(graph) { - while (token !== "" && token != "}") { + while (token !== '' && token != '}') { parseStatement(graph); - if (token === ";") { + if (token === ';') { getToken(); } } @@ -16491,16 +16401,16 @@ return /******/ (function(modules) { // webpackBootstrap // parse node if (tokenType != TOKENTYPE.IDENTIFIER) { - throw newSyntaxError("Identifier expected"); + throw newSyntaxError('Identifier expected'); } var id = token; // id can be a string or a number getToken(); - if (token === "=") { + if (token === '=') { // id statement getToken(); if (tokenType != TOKENTYPE.IDENTIFIER) { - throw newSyntaxError("Identifier expected"); + throw newSyntaxError('Identifier expected'); } graph[id] = token; getToken(); @@ -16519,9 +16429,9 @@ return /******/ (function(modules) { // webpackBootstrap var subgraph = null; // optional subgraph keyword - if (token === "subgraph") { + if (token === 'subgraph') { subgraph = {}; - subgraph.type = "subgraph"; + subgraph.type = 'subgraph'; getToken(); // optional graph id @@ -16532,7 +16442,7 @@ return /******/ (function(modules) { // webpackBootstrap } // open angle bracket - if (token === "{") { + if (token === '{') { getToken(); if (!subgraph) { @@ -16547,8 +16457,8 @@ return /******/ (function(modules) { // webpackBootstrap parseStatements(subgraph); // close angle bracket - if (token != "}") { - throw newSyntaxError("Angle bracket } expected"); + if (token != '}') { + throw newSyntaxError('Angle bracket } expected'); } getToken(); @@ -16579,24 +16489,24 @@ return /******/ (function(modules) { // webpackBootstrap */ function parseAttributeStatement(graph) { // attribute statements - if (token === "node") { + if (token === 'node') { getToken(); // node attributes graph.node = parseAttributeList(); - return "node"; - } else if (token === "edge") { + return 'node'; + } else if (token === 'edge') { getToken(); // edge attributes graph.edge = parseAttributeList(); - return "edge"; - } else if (token === "graph") { + return 'edge'; + } else if (token === 'graph') { getToken(); // graph attributes graph.graph = parseAttributeList(); - return "graph"; + return 'graph'; } return null; @@ -16628,7 +16538,7 @@ return /******/ (function(modules) { // webpackBootstrap * @param {String | Number} from Id of the from node */ function parseEdge(graph, from) { - while (token === "->" || token === "--") { + while (token === '->' || token === '--') { var to; var type = token; getToken(); @@ -16638,7 +16548,7 @@ return /******/ (function(modules) { // webpackBootstrap to = subgraph; } else { if (tokenType != TOKENTYPE.IDENTIFIER) { - throw newSyntaxError("Identifier or subgraph expected"); + throw newSyntaxError('Identifier or subgraph expected'); } to = token; addNode(graph, { @@ -16666,35 +16576,35 @@ return /******/ (function(modules) { // webpackBootstrap function parseAttributeList() { var attr = null; - while (token === "[") { + while (token === '[') { getToken(); attr = {}; - while (token !== "" && token != "]") { + while (token !== '' && token != ']') { if (tokenType != TOKENTYPE.IDENTIFIER) { - throw newSyntaxError("Attribute name expected"); + throw newSyntaxError('Attribute name expected'); } var name = token; getToken(); - if (token != "=") { - throw newSyntaxError("Equal sign = expected"); + if (token != '=') { + throw newSyntaxError('Equal sign = expected'); } getToken(); if (tokenType != TOKENTYPE.IDENTIFIER) { - throw newSyntaxError("Attribute value expected"); + throw newSyntaxError('Attribute value expected'); } var value = token; setValue(attr, name, value); // name can be a path getToken(); - if (token == ",") { + if (token == ',') { getToken(); } } - if (token != "]") { - throw newSyntaxError("Bracket ] expected"); + if (token != ']') { + throw newSyntaxError('Bracket ] expected'); } getToken(); } @@ -16708,7 +16618,7 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {SyntaxError} err */ function newSyntaxError(message) { - return new SyntaxError(message + ", got \"" + chop(token, 30) + "\" (char " + index + ")"); + return new SyntaxError(message + ', got "' + chop(token, 30) + '" (char ' + index + ')'); } /** @@ -16718,7 +16628,7 @@ return /******/ (function(modules) { // webpackBootstrap * @returns {String} */ function chop(text, maxLength) { - return text.length <= maxLength ? text : text.substr(0, 27) + "..."; + return text.length <= maxLength ? text : text.substr(0, 27) + '...'; } /** @@ -16773,7 +16683,7 @@ return /******/ (function(modules) { // webpackBootstrap }; merge(graphNode, dotNode.attr); if (graphNode.image) { - graphNode.shape = "image"; + graphNode.shape = 'image'; } graphData.nodes.push(graphNode); }); @@ -16786,13 +16696,13 @@ return /******/ (function(modules) { // webpackBootstrap * @param {Object} dotEdge * @returns {Object} graphEdge */ - var convertEdge = function (dotEdge) { + var convertEdge = function convertEdge(dotEdge) { var graphEdge = { from: dotEdge.from, to: dotEdge.to }; merge(graphEdge, dotEdge.attr); - graphEdge.style = dotEdge.type === "->" ? "arrow" : "line"; + graphEdge.style = dotEdge.type === '->' ? 'arrow' : 'line'; return graphEdge; }; @@ -16852,7 +16762,7 @@ return /******/ (function(modules) { // webpackBootstrap /* 39 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; function parseGephi(gephiJSON, options) { var edges = []; @@ -16917,29 +16827,29 @@ return /******/ (function(modules) { // webpackBootstrap /* 40 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; - // 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__(63); + 'use strict'; + + module.exports = typeof window !== 'undefined' && window.moment || __webpack_require__(64); /***/ }, /* 41 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; - // Only load hammer.js when in a browser environment // (loading hammer.js in a node.js environment gives errors) - if (typeof window !== "undefined") { - var propagating = __webpack_require__(69); - var Hammer = window.Hammer || __webpack_require__(70); + 'use strict'; + + if (typeof window !== 'undefined') { + var propagating = __webpack_require__(65); + var Hammer = window.Hammer || __webpack_require__(66); module.exports = propagating(Hammer, { preventDefault: true }); } else { module.exports = function () { - throw Error("hammer.js is only available in a browser, not in node.js."); + throw Error('hammer.js is only available in a browser, not in node.js.'); }; } @@ -17117,17 +17027,17 @@ return /******/ (function(modules) { // webpackBootstrap /* 43 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; var Emitter = __webpack_require__(42); var Hammer = __webpack_require__(41); - var hammerUtil = __webpack_require__(64); + var hammerUtil = __webpack_require__(44); var util = __webpack_require__(1); var DataSet = __webpack_require__(3); var DataView = __webpack_require__(4); var Range = __webpack_require__(17); var ItemSet = __webpack_require__(32); - var Activator = __webpack_require__(49); + var Activator = __webpack_require__(63); var DateUtil = __webpack_require__(15); var CustomTime = __webpack_require__(27); @@ -17153,43 +17063,43 @@ return /******/ (function(modules) { // webpackBootstrap 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 = 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); @@ -17211,10 +17121,10 @@ return /******/ (function(modules) { // webpackBootstrap this.dom.rightContainer.appendChild(this.dom.shadowTopRight); this.dom.rightContainer.appendChild(this.dom.shadowBottomRight); - this.on("rangechange", this.redraw.bind(this)); + this.on('rangechange', this.redraw.bind(this)); var me = this; - this.on("change", function (properties) { + this.on('change', function (properties) { if (properties && properties.queue == true) { // redraw once on next tick if (!me._redrawTimer) { @@ -17231,11 +17141,11 @@ return /******/ (function(modules) { // webpackBootstrap // create event listeners for all interesting events, these events will be // emitted via emitter - this.hammer = new Hammer(this.dom.root, { touchAction: "pan-y" }); - this.hammer.get("pinch").set({ enable: true }); + this.hammer = new Hammer(this.dom.root, { touchAction: 'pan-y' }); + this.hammer.get('pinch').set({ enable: true }); this.listeners = {}; - var events = ["tap", "doubletap", "press", "pinch", "pan", "panstart", "panmove", "panend" + var events = ['tap', 'doubletap', 'press', 'pinch', 'pan', 'panstart', 'panmove', 'panend' // TODO: cleanup //'touch', 'pinch', //'tap', 'doubletap', 'hold', @@ -17243,7 +17153,7 @@ return /******/ (function(modules) { // webpackBootstrap //'mousewheel', 'DOMMouseScroll' // DOMMouseScroll is needed for Firefox ]; events.forEach(function (type) { - var listener = function (event) { + var listener = function listener(event) { if (me.isActive()) { me.emit(type, event); } @@ -17254,16 +17164,16 @@ return /******/ (function(modules) { // webpackBootstrap // emulate a touch event (emitted before the start of a pan, pinch, tap, or press) hammerUtil.onTouch(this.hammer, (function (event) { - me.emit("touch", event); + me.emit('touch', event); }).bind(this)); function onMouseWheel(event) { if (me.isActive()) { - me.emit("mousewheel", event); + me.emit('mousewheel', event); } } - this.dom.root.addEventListener("mousewheel", onMouseWheel); - this.dom.root.addEventListener("DOMMouseScroll", onMouseWheel); + this.dom.root.addEventListener('mousewheel', onMouseWheel); + this.dom.root.addEventListener('DOMMouseScroll', onMouseWheel); // size properties of each of the panels this.props = { @@ -17285,7 +17195,7 @@ return /******/ (function(modules) { // webpackBootstrap this.redrawCount = 0; // attach the root panel to the provided container - if (!container) throw new Error("No container provided"); + if (!container) throw new Error('No container provided'); container.appendChild(this.dom.root); }; @@ -17317,14 +17227,14 @@ return /******/ (function(modules) { // webpackBootstrap Core.prototype.setOptions = function (options) { if (options) { // copy the known options - var fields = ["width", "height", "minHeight", "maxHeight", "autoResize", "start", "end", "orientation", "clickToUse", "dataAttributes", "hiddenDates"]; + var fields = ['width', 'height', 'minHeight', 'maxHeight', 'autoResize', 'start', 'end', 'orientation', 'clickToUse', 'dataAttributes', 'hiddenDates']; util.selectiveExtend(fields, this.options, options); - if ("hiddenDates" in this.options) { + if ('hiddenDates' in this.options) { DateUtil.convertHiddenOptions(this.body, this.options.hiddenDates); } - if ("clickToUse" in options) { + if ('clickToUse' in options) { if (options.clickToUse) { if (!this.activator) { this.activator = new Activator(this.dom.root); @@ -17348,7 +17258,7 @@ return /******/ (function(modules) { // webpackBootstrap // 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."); + throw new Error('Option order is deprecated. There is no replacement for this feature.'); } // redraw everything @@ -17405,7 +17315,6 @@ return /******/ (function(modules) { // webpackBootstrap this.body = null; }; - /** * Set a custom time bar * @param {Date} time @@ -17413,7 +17322,7 @@ return /******/ (function(modules) { // webpackBootstrap */ Core.prototype.setCustomTime = function (time, id) { if (!this.customTime) { - throw new Error("Cannot get custom time: Custom time bar is not enabled"); + throw new Error('Cannot get custom time: Custom time bar is not enabled'); } var barId = id || 0; @@ -17432,7 +17341,7 @@ return /******/ (function(modules) { // webpackBootstrap */ Core.prototype.getCustomTime = function (id) { if (!this.customTime) { - throw new Error("Cannot get custom time: Custom time bar is not enabled"); + throw new Error('Cannot get custom time: Custom time bar is not enabled'); } var barId = id || 0, @@ -17456,14 +17365,14 @@ return /******/ (function(modules) { // webpackBootstrap */ Core.prototype.addCustomTime = function (time, id) { if (!this.currentTime) { - throw new Error("Option showCurrentTime must be true"); + throw new Error('Option showCurrentTime must be true'); } if (time === undefined) { - throw new Error("Time parameter for the custom bar must be provided"); + throw new Error('Time parameter for the custom bar must be provided'); } - var ts = util.convert(time, "Date").valueOf(), + var ts = util.convert(time, 'Date').valueOf(), numIds, customTime, customBarId; @@ -17476,16 +17385,18 @@ return /******/ (function(modules) { // webpackBootstrap // If the ID is not provided, generate one, otherwise just use it if (id === undefined) { + numIds = this.customBarIds.filter(function (element) { return util.isNumber(element); }); customBarId = numIds.length > 0 ? Math.max.apply(null, numIds) + 1 : 1; } else { + // Check for duplicates this.customBarIds.forEach(function (element) { if (element === id) { - throw new Error("Custom time ID already exists"); + throw new Error('Custom time ID already exists'); } }); @@ -17512,6 +17423,7 @@ return /******/ (function(modules) { // webpackBootstrap * @return {boolean} True if the bar exists and is removed, false otherwise */ Core.prototype.removeCustomTime = function (id) { + var me = this; this.components.forEach(function (bar, index, components) { @@ -17526,7 +17438,6 @@ return /******/ (function(modules) { // webpackBootstrap }); }; - /** * Get the id's of the currently visible items. * @returns {Array} The ids of the visible items @@ -17535,8 +17446,6 @@ return /******/ (function(modules) { // webpackBootstrap return this.itemSet && this.itemSet.getVisibleItems() || []; }; - - /** * Clear the Core. By Default, items, groups and options are cleared. * Example usage: @@ -17661,7 +17570,7 @@ return /******/ (function(modules) { // webpackBootstrap */ Core.prototype.moveTo = function (time, options) { var interval = this.range.end - this.range.start; - var t = util.convert(time, "Date").valueOf(); + var t = util.convert(time, 'Date').valueOf(); var start = t - interval / 2; var end = t + interval / 2; @@ -17705,18 +17614,18 @@ return /******/ (function(modules) { // webpackBootstrap DateUtil.updateHiddenDates(this.body, this.options.hiddenDates); // update class names - if (options.orientation == "top") { - util.addClassName(dom.root, "top"); - util.removeClassName(dom.root, "bottom"); + if (options.orientation == 'top') { + util.addClassName(dom.root, 'top'); + util.removeClassName(dom.root, 'bottom'); } else { - util.removeClassName(dom.root, "top"); - util.addClassName(dom.root, "bottom"); + util.removeClassName(dom.root, 'top'); + util.addClassName(dom.root, 'bottom'); } // 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, ""); + 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; @@ -17750,7 +17659,7 @@ return /******/ (function(modules) { // webpackBootstrap // 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"); + dom.root.style.height = util.option.asSize(options.height, autoHeight + 'px'); // calculate heights of the content panels props.root.height = dom.root.offsetHeight; @@ -17774,37 +17683,37 @@ return /******/ (function(modules) { // webpackBootstrap props.bottom.width = centerWidth; // resize the panels - dom.background.style.height = props.background.height + "px"; - dom.backgroundVertical.style.height = props.background.height + "px"; - dom.backgroundHorizontal.style.height = props.centerContainer.height + "px"; - dom.centerContainer.style.height = props.centerContainer.height + "px"; - dom.leftContainer.style.height = props.leftContainer.height + "px"; - dom.rightContainer.style.height = props.rightContainer.height + "px"; - - dom.background.style.width = props.background.width + "px"; - dom.backgroundVertical.style.width = props.centerContainer.width + "px"; - dom.backgroundHorizontal.style.width = props.background.width + "px"; - dom.centerContainer.style.width = props.center.width + "px"; - dom.top.style.width = props.top.width + "px"; - dom.bottom.style.width = props.bottom.width + "px"; + dom.background.style.height = props.background.height + 'px'; + dom.backgroundVertical.style.height = props.background.height + 'px'; + dom.backgroundHorizontal.style.height = props.centerContainer.height + 'px'; + dom.centerContainer.style.height = props.centerContainer.height + 'px'; + dom.leftContainer.style.height = props.leftContainer.height + 'px'; + dom.rightContainer.style.height = props.rightContainer.height + 'px'; + + dom.background.style.width = props.background.width + 'px'; + dom.backgroundVertical.style.width = props.centerContainer.width + 'px'; + dom.backgroundHorizontal.style.width = props.background.width + 'px'; + dom.centerContainer.style.width = props.center.width + 'px'; + dom.top.style.width = props.top.width + 'px'; + dom.bottom.style.width = props.bottom.width + 'px'; // reposition the panels - dom.background.style.left = "0"; - dom.background.style.top = "0"; - dom.backgroundVertical.style.left = props.left.width + 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"; + 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 @@ -17812,19 +17721,19 @@ return /******/ (function(modules) { // webpackBootstrap // reposition the scrollable contents var offset = this.props.scrollTop; - if (options.orientation == "bottom") { + 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"; + dom.center.style.left = '0'; + dom.center.style.top = offset + 'px'; + dom.left.style.left = '0'; + dom.left.style.top = offset + 'px'; + dom.right.style.left = '0'; + dom.right.style.top = offset + 'px'; // show shadows when vertical scrolling is available - var visibilityTop = this.props.scrollTop == 0 ? "hidden" : ""; - var visibilityBottom = this.props.scrollTop == this.props.scrollTopMin ? "hidden" : ""; + 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; @@ -17843,17 +17752,17 @@ return /******/ (function(modules) { // webpackBootstrap this.redrawCount++; this._redraw(); } else { - console.log("WARNING: infinite loop in redraw?"); + console.log('WARNING: infinite loop in redraw?'); } this.redrawCount = 0; } - this.emit("finishedRedraw"); + 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."); + throw new Error('Function repaint is deprecated. Use redraw instead.'); }; /** @@ -17865,7 +17774,7 @@ return /******/ (function(modules) { // webpackBootstrap */ Core.prototype.setCurrentTime = function (time) { if (!this.currentTime) { - throw new Error("Option showCurrentTime must be true"); + throw new Error('Option showCurrentTime must be true'); } this.currentTime.setCurrentTime(time); @@ -17878,7 +17787,7 @@ return /******/ (function(modules) { // webpackBootstrap */ Core.prototype.getCurrentTime = function () { if (!this.currentTime) { - throw new Error("Option showCurrentTime must be true"); + throw new Error('Option showCurrentTime must be true'); } return this.currentTime.getCurrentTime(); @@ -17920,8 +17829,6 @@ return /******/ (function(modules) { // webpackBootstrap return DateUtil.toScreen(this, time, this.props.center.width); }; - - /** * 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 @@ -17937,7 +17844,6 @@ return /******/ (function(modules) { // webpackBootstrap //return (time.valueOf() - conversion.offset) * conversion.scale; }; - /** * Initialize watching when option autoResize is true * @private @@ -17976,13 +17882,13 @@ return /******/ (function(modules) { // webpackBootstrap me.props.lastWidth = me.dom.root.offsetWidth; me.props.lastHeight = me.dom.root.offsetHeight; - me.emit("change"); + me.emit('change'); } } }; // add event listener to window resize - util.addEventListener(window, "resize", this._onResize); + util.addEventListener(window, 'resize', this._onResize); this.watchTimer = setInterval(this._onResize, 1000); }; @@ -17998,7 +17904,7 @@ return /******/ (function(modules) { // webpackBootstrap } // remove event listener on window.resize - util.removeEventListener(window, "resize", this._onResize); + util.removeEventListener(window, 'resize', this._onResize); this._onResize = null; }; @@ -18025,7 +17931,7 @@ return /******/ (function(modules) { // webpackBootstrap 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") { + if (this.options.orientation == 'bottom') { this.props.scrollTop += scrollTopMin - this.props.scrollTopMin; } this.props.scrollTopMin = scrollTopMin; @@ -18053,32 +17959,86 @@ return /******/ (function(modules) { // webpackBootstrap /* 44 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; + + var Hammer = __webpack_require__(41); + + /** + * Register a touch event, taking place before a gesture + * @param {Hammer} hammer A hammer instance + * @param {function} callback Callback, called as callback(event) + */ + exports.onTouch = function (hammer, callback) { + callback.inputHandler = function (event) { + if (event.isFirst) { + callback(event); + } + }; + + hammer.on('hammer.input', callback.inputHandler); + }; + + /** + * Register a release event, taking place after a gesture + * @param {Hammer} hammer A hammer instance + * @param {function} callback Callback, called as callback(event) + */ + exports.onRelease = function (hammer, callback) { + callback.inputHandler = function (event) { + if (event.isFinal) { + callback(event); + } + }; + + return hammer.on('hammer.input', callback.inputHandler); + }; + + /** + * Unregister a touch event, taking place before a gesture + * @param {Hammer} hammer A hammer instance + * @param {function} callback Callback, called as callback(event) + */ + exports.offTouch = function (hammer, callback) { + hammer.off('hammer.input', callback.inputHandler); + }; + + /** + * Unregister a release event, taking place before a gesture + * @param {Hammer} hammer A hammer instance + * @param {function} callback Callback, called as callback(event) + */ + exports.offRelease = exports.offTouch; + +/***/ }, +/* 45 */ +/***/ function(module, exports, __webpack_require__) { // English + 'use strict'; + exports.en = { - current: "current", - time: "time" + current: 'current', + time: 'time' }; exports.en_EN = exports.en; exports.en_US = exports.en; // Dutch exports.nl = { - custom: "aangepaste", - time: "tijd" + custom: 'aangepaste', + time: 'tijd' }; exports.nl_NL = exports.nl; exports.nl_BE = exports.nl; /***/ }, -/* 45 */ +/* 46 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; var DOMutil = __webpack_require__(2); - var Points = __webpack_require__(47); + var Points = __webpack_require__(48); function Line(groupId, options) { this.groupId = groupId; @@ -18095,7 +18055,6 @@ return /******/ (function(modules) { // webpackBootstrap return { min: yMin, max: yMax, yAxisOrientation: this.options.yAxisOrientation }; }; - /** * draw a line graph * @@ -18106,11 +18065,11 @@ return /******/ (function(modules) { // webpackBootstrap 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); + 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); + path.setAttributeNS(null, 'style', group.style); } // construct path from dataset @@ -18122,21 +18081,21 @@ return /******/ (function(modules) { // webpackBootstrap // 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 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; + 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; + dFill = 'M' + dataset[0].x + ',' + svgHeight + ' ' + d + 'L' + dataset[dataset.length - 1].x + ',' + svgHeight; } - fillPath.setAttributeNS(null, "class", group.className + " fill"); + fillPath.setAttributeNS(null, 'class', group.className + ' fill'); if (group.options.shaded.style !== undefined) { - fillPath.setAttributeNS(null, "style", group.options.shaded.style); + fillPath.setAttributeNS(null, 'style', group.options.shaded.style); } - fillPath.setAttributeNS(null, "d", dFill); + fillPath.setAttributeNS(null, 'd', dFill); } // copy properties to path for drawing. - path.setAttributeNS(null, "d", "M" + d); + path.setAttributeNS(null, 'd', 'M' + d); // draw points if (group.options.drawPoints.enabled == true) { @@ -18146,8 +18105,6 @@ return /******/ (function(modules) { // webpackBootstrap } }; - - /** * This uses an uniform parametrization of the CatmullRom algorithm: * 'On the Parameterization of Catmull-Rom Curves' by Cem Yuksel et al. @@ -18158,16 +18115,16 @@ return /******/ (function(modules) { // webpackBootstrap 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 d = Math.round(data[0].x) + ',' + Math.round(data[0].y) + ' '; var normalization = 1 / 6; var length = data.length; for (var i = 0; i < length - 1; i++) { + p0 = i == 0 ? data[0] : data[i - 1]; p1 = data[i]; p2 = data[i + 1]; p3 = i + 2 < length ? data[i + 2] : p2; - // Catmull-Rom to Cubic Bezier conversion matrix // 0 1 0 0 // -1/6 1 1/6 0 @@ -18179,7 +18136,7 @@ return /******/ (function(modules) { // webpackBootstrap bp2 = { x: (p1.x + 6 * p2.x - p3.x) * normalization, y: (p1.y + 6 * p2.y - p3.y) * normalization }; // bp0 = { x: p2.x, y: p2.y }; - d += "C" + bp1.x + "," + bp1.y + " " + bp2.x + "," + bp2.y + " " + p2.x + "," + p2.y + " "; + d += 'C' + bp1.x + ',' + bp1.y + ' ' + bp2.x + ',' + bp2.y + ' ' + p2.x + ',' + p2.y + ' '; } return d; @@ -18203,9 +18160,10 @@ return /******/ (function(modules) { // webpackBootstrap } 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 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]; @@ -18255,7 +18213,7 @@ return /******/ (function(modules) { // webpackBootstrap if (bp2.x == 0 && bp2.y == 0) { bp2 = p2; } - d += "C" + bp1.x + "," + bp1.y + " " + bp2.x + "," + bp2.y + " " + p2.x + "," + p2.y + " "; + d += 'C' + bp1.x + ',' + bp1.y + ' ' + bp2.x + ',' + bp2.y + ' ' + p2.x + ',' + p2.y + ' '; } return d; @@ -18270,12 +18228,12 @@ return /******/ (function(modules) { // webpackBootstrap */ Line._linear = function (data) { // linear - var d = ""; + var d = ''; for (var i = 0; i < data.length; i++) { if (i == 0) { - d += data[i].x + "," + data[i].y; + d += data[i].x + ',' + data[i].y; } else { - d += " " + data[i].x + "," + data[i].y; + d += ' ' + data[i].x + ',' + data[i].y; } } return d; @@ -18284,13 +18242,13 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = Line; /***/ }, -/* 46 */ +/* 47 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; var DOMutil = __webpack_require__(2); - var Points = __webpack_require__(47); + var Points = __webpack_require__(48); function Bargraph(groupId, options) { this.groupId = groupId; @@ -18298,7 +18256,7 @@ return /******/ (function(modules) { // webpackBootstrap } Bargraph.prototype.getYRange = function (groupData) { - if (this.options.barChart.handleOverlap != "stack") { + if (this.options.barChart.handleOverlap != 'stack') { var yMin = groupData[0].y; var yMax = groupData[0].y; for (var j = 0; j < groupData.length; j++) { @@ -18319,8 +18277,6 @@ return /******/ (function(modules) { // webpackBootstrap } }; - - /** * draw a bar graph * @@ -18339,7 +18295,7 @@ return /******/ (function(modules) { // webpackBootstrap // combine all barchart data for (i = 0; i < groupIds.length; i++) { group = framework.groups[groupIds[i]]; - if (group.options.style == "bar") { + if (group.options.style == 'bar') { if (group.visible == true && (framework.options.groups.visibility[groupIds[i]] === undefined || framework.options.groups.visibility[groupIds[i]] == true)) { for (j = 0; j < processedGroupData[groupIds[i]].length; j++) { combinedData.push({ @@ -18397,20 +18353,20 @@ return /******/ (function(modules) { // webpackBootstrap drawData = Bargraph._getSafeDrawData(coreDistance, group, minWidth); intersections[key].resolved += 1; - if (group.options.barChart.handleOverlap == "stack") { + if (group.options.barChart.handleOverlap == 'stack') { heightOffset = intersections[key].accumulated; intersections[key].accumulated += group.zeroPosition - combinedData[i].y; - } else if (group.options.barChart.handleOverlap == "sideBySide") { + } else if (group.options.barChart.handleOverlap == 'sideBySide') { drawData.width = drawData.width / intersections[key].amount; drawData.offset += intersections[key].resolved * drawData.width - 0.5 * drawData.width * (intersections[key].amount + 1); - if (group.options.barChart.align == "left") { + if (group.options.barChart.align == 'left') { drawData.offset -= 0.5 * drawData.width; - } else if (group.options.barChart.align == "right") { + } else if (group.options.barChart.align == 'right') { drawData.offset += 0.5 * drawData.width; } } } - 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); + 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) { Points.draw([combinedData[i]], group, framework, drawData.offset); @@ -18419,7 +18375,6 @@ return /******/ (function(modules) { // webpackBootstrap } }; - /** * Fill the intersections object with counters of how many datapoints share the same x coordinates * @param intersections @@ -18445,7 +18400,6 @@ return /******/ (function(modules) { // webpackBootstrap } }; - /** * Get the width and offset for bargraphs based on the coredistance between datapoints * @@ -18461,18 +18415,18 @@ return /******/ (function(modules) { // webpackBootstrap width = coreDistance < minWidth ? minWidth : coreDistance; offset = 0; // recalculate offset with the new width; - if (group.options.barChart.align == "left") { + if (group.options.barChart.align == 'left') { offset -= 0.5 * coreDistance; - } else if (group.options.barChart.align == "right") { + } else if (group.options.barChart.align == 'right') { offset += 0.5 * coreDistance; } } else { // default settings width = group.options.barChart.width; offset = 0; - if (group.options.barChart.align == "left") { + if (group.options.barChart.align == 'left') { offset -= 0.5 * group.options.barChart.width; - } else if (group.options.barChart.align == "right") { + } else if (group.options.barChart.align == 'right') { offset += 0.5 * group.options.barChart.width; } } @@ -18525,10 +18479,10 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = Bargraph; /***/ }, -/* 47 */ +/* 48 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; var DOMutil = __webpack_require__(2); @@ -18537,7 +18491,6 @@ return /******/ (function(modules) { // webpackBootstrap this.options = options; } - Points.prototype.getYRange = function (groupData) { var yMin = groupData[0].y; var yMax = groupData[0].y; @@ -18570,619 +18523,886 @@ return /******/ (function(modules) { // webpackBootstrap } }; - module.exports = Points; /***/ }, -/* 48 */ +/* 49 */ /***/ function(module, exports, __webpack_require__) { "use strict"; + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + Object.defineProperty(exports, "__esModule", { + value: true + }); + var util = __webpack_require__(1); + /** - * Canvas shapes used by Network + * @class Groups + * This class can store groups and options specific for groups. */ - 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 Groups = (function () { + function Groups() { + _classCallCheck(this, Groups); - // the change in radius and the offset is here to center the shape - r *= 1.15; - y += 0.275 * r; + this.clear(); + this.defaultIndex = 0; + this.groupsArray = []; + this.groupIndex = 0; - 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.defaultGroups = [{ 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 + { border: "#990000", background: "#EE0000", highlight: { border: "#BB0000", background: "#FF3333" }, hover: { border: "#BB0000", background: "#FF3333" } }, // 10:bright red - 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(); + { 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 - }; + { border: "#EE0000", background: "#990000", highlight: { border: "#FF3333", background: "#BB0000" }, hover: { border: "#FF3333", background: "#BB0000" } }]; - /** - * 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(); + this.options = {}; + this.defaultOptions = { + useDefaultGroups: true + }; + util.extend(this.options, this.defaultOptions); + } - // the change in radius and the offset is here to center the shape - r *= 1.15; - y -= 0.275 * r; + _createClass(Groups, [{ + key: "setOptions", + value: function setOptions(options) { + var optionFields = ["useDefaultGroups"]; - 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 (options !== undefined) { + for (var groupName in options) { + if (options.hasOwnProperty(groupName)) { + if (optionFields.indexOf(groupName) === -1) { + var group = options[groupName]; + this.add(groupName, group); + } + } + } + } + } + }, { + key: "clear", - 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(); - }; + /** + * Clear all groups + */ + value: function clear() { + this.groups = {}; + this.groupsArray = []; + } + }, { + key: "get", - /** - * 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(); + /** + * get group options 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 options + */ + value: function get(groupname) { + var group = this.groups[groupname]; + if (group === undefined) { + if (this.options.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 % this.defaultGroups.length; + this.defaultIndex++; + group = {}; + group.color = this.defaultGroups[index]; + this.groups[groupname] = group; + } + } - // the change in radius and the offset is here to center the shape - r *= 0.82; - y += 0.1 * r; + return group; + } + }, { + key: "add", - 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)); + /** + * Add a custom group style + * @param {String} groupName + * @param {Object} style An object containing borderColor, + * backgroundColor, etc. + * @return {Object} group The created group object + */ + value: function add(groupName, style) { + this.groups[groupName] = style; + this.groupsArray.push(groupName); + return style; } + }]); - this.closePath(); - }; + return Groups; + })(); - /** - * Draw a Diamond 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.diamond = function (x, y, r) { - // http://www.html5canvastutorials.com/labs/html5-canvas-star-spinner/ - this.beginPath(); + exports["default"] = Groups; + module.exports = exports["default"]; + // 20:bright red - this.lineTo(x, y + r); - this.lineTo(x + r, y); - this.lineTo(x, y - r); - this.lineTo(x - r, y); +/***/ }, +/* 50 */ +/***/ function(module, exports, __webpack_require__) { + 'use strict'; - this.closePath(); - }; + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; - /** - * http://stackoverflow.com/questions/1255512/how-to-draw-a-rounded-rectangle-on-html-canvas - */ - CanvasRenderingContext2D.prototype.roundRect = function (x, y, w, h, r) { - var r2d = Math.PI / 180; - if (w - 2 * r < 0) { - r = w / 2; - } //ensure that the radius isn't too large for x - if (h - 2 * r < 0) { - r = h / 2; - } //ensure that the radius isn't too large for y - this.beginPath(); - this.moveTo(x + r, y); - this.lineTo(x + w - r, y); - this.arc(x + w - r, y + r, r, r2d * 270, r2d * 360, false); - this.lineTo(x + w, y + h - r); - this.arc(x + w - r, y + h - r, r, 0, r2d * 90, false); - this.lineTo(x + r, y + h); - this.arc(x + r, y + h - r, r, r2d * 90, r2d * 180, false); - this.lineTo(x, y + r); - this.arc(x + r, y + r, r, r2d * 180, r2d * 270, false); - }; + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; - /** - * http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas - */ - CanvasRenderingContext2D.prototype.ellipse = function (x, y, w, h) { - var kappa = 0.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 + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); - 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); - }; + Object.defineProperty(exports, '__esModule', { + value: true + }); + var _Node = __webpack_require__(67); - /** - * 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 _Node2 = _interopRequireWildcard(_Node); - var kappa = 0.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 + var _Label = __webpack_require__(68); - this.beginPath(); - this.moveTo(xe, ym); + var _Label2 = _interopRequireWildcard(_Label); - this.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); - this.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); + var util = __webpack_require__(1); + var DataSet = __webpack_require__(3); + var DataView = __webpack_require__(4); - this.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); - this.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); + var NodesHandler = (function () { + function NodesHandler(body, images, groups, layoutEngine) { + var _this = this; - this.lineTo(xe, ymb); + _classCallCheck(this, NodesHandler); - this.bezierCurveTo(xe, ymb + oy, xm + ox, yeb, xm, yeb); - this.bezierCurveTo(xm - ox, yeb, x, ymb + oy, x, ymb); + this.body = body; + this.images = images; + this.groups = groups; + this.layoutEngine = layoutEngine; - this.lineTo(x, ym); - }; + // create the node API in the body container + this.body.functions.createNode = this.create.bind(this); + this.nodesListeners = { + add: function add(event, params) { + _this.add(params.items); + }, + update: function update(event, params) { + _this.update(params.items, params.data); + }, + remove: function remove(event, params) { + _this.remove(params.items); + } + }; - /** - * 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); + this.options = {}; + this.defaultOptions = { + borderWidth: 1, + borderWidthSelected: undefined, + brokenImage: undefined, + color: { + border: '#2B7CE9', + background: '#97C2FC', + highlight: { + border: '#2B7CE9', + background: '#D2E5FF' + }, + hover: { + border: '#2B7CE9', + background: '#D2E5FF' + } + }, + fixed: { + x: false, + y: false + }, + font: { + color: '#343434', + size: 14, // px + face: 'arial', + background: 'none', + stroke: 0, // px + strokeColor: '#ffffff', + align: 'horizontal' + }, + group: undefined, + hidden: false, + icon: { + face: 'FontAwesome', //'FontAwesome', + code: undefined, //'\uf007', + size: 50, //50, + color: '#2B7CE9' //'#aa00ff' + }, + image: undefined, // --> URL + label: undefined, + level: undefined, + mass: 1, + physics: true, + scaling: { + min: 10, + max: 30, + label: { + enabled: true, + min: 14, + max: 30, + maxVisible: 30, + drawThreshold: 3 + }, + customScalingFunction: function customScalingFunction(min, max, total, value) { + if (max === min) { + return 0.5; + } else { + var scale = 1 / (max - min); + return Math.max(0, (value - min) * scale); + } + } + }, + shape: 'ellipse', + size: 25, + title: undefined, + value: 1, + x: undefined, + y: undefined + }; + util.extend(this.options, this.defaultOptions); + } - // 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); + _createClass(NodesHandler, [{ + key: 'setOptions', + value: function setOptions(options) { + if (options !== undefined) { + _Node2['default'].parseOptions(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); + // update the shape in all nodes + if (options.shape !== undefined) { + for (var nodeId in this.body.nodes) { + if (this.body.nodes.hasOwnProperty(nodeId)) { + this.body.nodes[nodeId].updateShape(); + } + } + } - // 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); + // update the shape size in all nodes + if (options.font !== undefined) { + _Label2['default'].parseOptions(this.options.font, options); + for (var nodeId in this.body.nodes) { + if (this.body.nodes.hasOwnProperty(nodeId)) { + this.body.nodes[nodeId].updateLabelModule(); + this.body.nodes[nodeId]._reset(); + } + } + } - this.beginPath(); - this.moveTo(x, y); - this.lineTo(xl, yl); - this.lineTo(xi, yi); - this.lineTo(xr, yr); - this.closePath(); - }; + // update the shape size in all nodes + if (options.size !== undefined) { + for (var nodeId in this.body.nodes) { + if (this.body.nodes.hasOwnProperty(nodeId)) { + this.body.nodes[nodeId]._reset(); + } + } + } - /** - * 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; + // update the state of the variables if needed + if (options.hidden !== undefined || options.physics !== undefined) { + this.body.emitter.emit('_dataChanged'); + } + } } - }; + }, { + key: 'setData', - // TODO: add diamond shape - } + /** + * Set a data set with nodes for the network + * @param {Array | DataSet | DataView} nodes The data containing the nodes. + * @private + */ + value: function setData(nodes) { + var doNotEmit = arguments[1] === undefined ? false : arguments[1]; + + var oldNodesData = this.body.data.nodes; + + if (nodes instanceof DataSet || nodes instanceof DataView) { + this.body.data.nodes = nodes; + } else if (Array.isArray(nodes)) { + this.body.data.nodes = new DataSet(); + this.body.data.nodes.add(nodes); + } else if (!nodes) { + this.body.data.nodes = new DataSet(); + } else { + throw new TypeError('Array or DataSet expected'); + } -/***/ }, -/* 49 */ -/***/ function(module, exports, __webpack_require__) { + if (oldNodesData) { + // unsubscribe from old dataset + util.forEach(this.nodesListeners, function (callback, event) { + oldNodesData.off(event, callback); + }); + } - "use strict"; + // remove drawn nodes + this.body.nodes = {}; - var keycharm = __webpack_require__(65); - var Emitter = __webpack_require__(42); - var Hammer = __webpack_require__(41); - var util = __webpack_require__(1); + if (this.body.data.nodes) { + // subscribe to new dataset + var me = this; + util.forEach(this.nodesListeners, function (callback, event) { + me.body.data.nodes.on(event, callback); + }); - /** - * 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; + // draw all new nodes + var ids = this.body.data.nodes.getIds(); + this.add(ids, true); + } - this.dom = { - container: container - }; + if (doNotEmit === false) { + this.body.emitter.emit('_dataChanged'); + } + } + }, { + key: 'add', - this.dom.overlay = document.createElement("div"); - this.dom.overlay.className = "overlay"; + /** + * Add nodes + * @param {Number[] | String[]} ids + * @private + */ + value: function add(ids) { + var doNotEmit = arguments[1] === undefined ? false : arguments[1]; - this.dom.container.appendChild(this.dom.overlay); + var id; + var newNodes = []; + for (var i = 0; i < ids.length; i++) { + id = ids[i]; + var properties = this.body.data.nodes.get(id); + var node = this.create(properties);; + newNodes.push(node); + this.body.nodes[id] = node; // note: this may replace an existing node + } - this.hammer = Hammer(this.dom.overlay, { prevent_default: false }); - this.hammer.on("tap", this._onTapOverlay.bind(this)); + this.layoutEngine.positionInitially(newNodes); - // 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(); - }); - }); + if (doNotEmit === false) { + this.body.emitter.emit('_dataChanged'); + } + } + }, { + key: 'update', - // 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(); + /** + * Update existing nodes, or create them when not yet existing + * @param {Number[] | String[]} ids + * @private + */ + value: function update(ids, changedData) { + var nodes = this.body.nodes; + var dataChanged = false; + for (var i = 0; i < ids.length; i++) { + var id = ids[i]; + var node = nodes[id]; + var data = changedData[i]; + if (node !== undefined) { + // update node + node.setOptions(data, this.constants); + } else { + dataChanged = true; + // create node + node = this.create(properties); + nodes[id] = node; + } + } + + if (dataChanged === true) { + this.body.emitter.emit('_dataChanged'); + } else { + this.body.emitter.emit('_dataUpdated'); + } } - }); + }, { + key: 'remove', - if (this.keycharm !== undefined) { - this.keycharm.destroy(); - } - this.keycharm = keycharm(); + /** + * Remove existing nodes. If nodes do not exist, the method will just ignore it. + * @param {Number[] | String[]} ids + * @private + */ + value: function remove(ids) { + var nodes = this.body.nodes; - // 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); + for (var i = 0; i < ids.length; i++) { + var id = ids[i]; + delete nodes[id]; + } - // cleanup hammer instances - this.hammer = null; - this.windowHammer = null; - // FIXME: cleaning up hammer instances doesn't work (Timeline not removed from memory) - }; + this.body.emitter.emit('_dataChanged'); + } + }, { + key: 'create', + value: function create(properties) { + var constructorClass = arguments[1] === undefined ? _Node2['default'] : arguments[1]; - /** - * Activate the element - * Overlay is hidden, element is decorated with a blue shadow border - */ - Activator.prototype.activate = function () { - // we allow only one active activator at a time - if (Activator.current) { - Activator.current.deactivate(); - } - Activator.current = this; + return new constructorClass(properties, this.body, this.images, this.groups, this.options); + } + }]); - this.active = true; - this.dom.overlay.style.display = "none"; - util.addClassName(this.dom.container, "vis-active"); + return NodesHandler; + })(); - this.emit("change"); - this.emit("activate"); + exports['default'] = NodesHandler; + module.exports = exports['default']; - // 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); - }; +/***/ }, +/* 51 */ +/***/ function(module, exports, __webpack_require__) { - /** - * 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); + 'use strict'; - this.emit("change"); - this.emit("deactivate"); - }; + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; - /** - * Handle a tap event: activate the container - * @param event - * @private - */ - Activator.prototype._onTapOverlay = function (event) { - // activate the container - this.activate(); - event.stopPropagation(); - }; + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; - /** - * Test whether the element has the requested parent element somewhere in - * its chain of parent nodes. - * @param {HTMLElement} element - * @param {HTMLElement} parent - * @returns {boolean} Returns true when the parent is found somewhere in the - * chain of parent nodes. - * @private - */ - function _hasParent(element, parent) { - while (element) { - if (element === parent) { - return true; - } - element = element.parentNode; - } - return false; - } + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); - module.exports = Activator; + Object.defineProperty(exports, '__esModule', { + value: true + }); -/***/ }, -/* 50 */ -/***/ function(module, exports, __webpack_require__) { + var _Edge = __webpack_require__(69); - "use strict"; + var _Edge2 = _interopRequireWildcard(_Edge); - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; + var _Label = __webpack_require__(68); - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var _Label2 = _interopRequireWildcard(_Label); var util = __webpack_require__(1); + var DataSet = __webpack_require__(3); + var DataView = __webpack_require__(4); - /** - * @class Groups - * This class can store groups and options specific for groups. - */ - var Groups = (function () { - function Groups() { - _classCallCheck(this, Groups); - - this.clear(); - this.defaultIndex = 0; - this.groupsArray = []; - this.groupIndex = 0; + var EdgesHandler = (function () { + function EdgesHandler(body, images, groups) { + var _this = this; - this.defaultGroups = [{ 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 + _classCallCheck(this, EdgesHandler); - { border: "#990000", background: "#EE0000", highlight: { border: "#BB0000", background: "#FF3333" }, hover: { border: "#BB0000", background: "#FF3333" } }, // 10:bright red + this.body = body; + this.images = images; + this.groups = groups; - { 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 edge API in the body container + this.body.functions.createEdge = this.create.bind(this); - { border: "#EE0000", background: "#990000", highlight: { border: "#FF3333", background: "#BB0000" }, hover: { border: "#FF3333", background: "#BB0000" } }]; + this.edgesListeners = { + add: function add(event, params) { + _this.add(params.items); + }, + update: function update(event, params) { + _this.update(params.items); + }, + remove: function remove(event, params) { + _this.remove(params.items); + } + }; this.options = {}; this.defaultOptions = { - useDefaultGroups: true + arrows: { + to: { enabled: false, scaleFactor: 1 }, // boolean / {arrowScaleFactor:1} / {enabled: false, arrowScaleFactor:1} + middle: { enabled: false, scaleFactor: 1 }, + from: { enabled: false, scaleFactor: 1 } + }, + color: { + color: '#848484', + highlight: '#848484', + hover: '#848484', + inherit: { + enabled: true, + source: 'from', // from / true + useGradients: false // release in 4.0 + }, + opacity: 1 + }, + dashes: { + enabled: false, + preset: 'dotted', + length: 10, + gap: 5, + altLength: undefined + }, + font: { + color: '#343434', + size: 14, // px + face: 'arial', + background: 'none', + stroke: 1, // px + strokeColor: '#ffffff', + align: 'horizontal' + }, + hidden: false, + hoverWidth: 1.5, + label: undefined, + length: undefined, + physics: true, + scaling: { + min: 1, + max: 15, + label: { + enabled: true, + min: 14, + max: 30, + maxVisible: 30, + drawThreshold: 3 + }, + customScalingFunction: function customScalingFunction(min, max, total, value) { + if (max === min) { + return 0.5; + } else { + var scale = 1 / (max - min); + return Math.max(0, (value - min) * scale); + } + } + }, + selfReferenceSize: 20, + smooth: { + enabled: true, + dynamic: true, + type: 'continuous', + roundness: 0.5 + }, + title: undefined, + width: 1, + widthSelectionMultiplier: 2, + value: 1 }; + util.extend(this.options, this.defaultOptions); + + // this allows external modules to force all dynamic curves to turn static. + this.body.emitter.on('_forceDisableDynamicCurves', function (type) { + var emitChange = false; + for (var edgeId in _this.body.edges) { + if (_this.body.edges.hasOwnProperty(edgeId)) { + var edgeOptions = _this.body.edges[edgeId].options.smooth; + if (edgeOptions.enabled === true && edgeOptions.dynamic === true) { + if (type === undefined) { + edge.setOptions({ smooth: false }); + } else { + edge.setOptions({ smooth: { dynamic: false, type: type } }); + } + emitChange = true; + } + } + } + if (emitChange === true) { + _this.body.emitter.emit('_dataChanged'); + } + }); + + // this is called when options of EXISTING nodes or edges have changed. + this.body.emitter.on('_dataUpdated', function () { + _this.reconnectEdges(); + _this.markAllEdgesAsDirty(); + }); } - _prototypeProperties(Groups, null, { - setOptions: { - value: function setOptions(options) { - var optionFields = ["useDefaultGroups"]; + _createClass(EdgesHandler, [{ + key: 'setOptions', + value: function setOptions(options) { + if (options !== undefined) { + // use the parser from the Edge class to fill in all shorthand notations + _Edge2['default'].parseOptions(this.options, options); - if (options !== undefined) { - for (var groupName in options) { - if (options.hasOwnProperty(groupName)) { - if (optionFields.indexOf(groupName) === -1) { - var group = options[groupName]; - this.add(groupName, group); - } + // hanlde multiple input cases for color + if (options.color !== undefined) { + this.markAllEdgesAsDirty(); + } + + // update smooth settings in all edges + var dataChanged = false; + if (options.smooth !== undefined) { + for (var edgeId in this.body.edges) { + if (this.body.edges.hasOwnProperty(edgeId)) { + dataChanged = this.body.edges[edgeId].updateEdgeType() || dataChanged; } } } - }, - writable: true, - configurable: true - }, - clear: { + // update fonts in all edges + if (options.font !== undefined) { + // use the parser from the Label class to fill in all shorthand notations + _Label2['default'].parseOptions(this.options, options); + for (var edgeId in this.body.edges) { + if (this.body.edges.hasOwnProperty(edgeId)) { + this.body.edges[edgeId].updateLabelModule(); + } + } + } - /** - * Clear all groups - */ - value: function clear() { - this.groups = {}; - this.groupsArray = []; - }, - writable: true, - configurable: true - }, - get: { + // update the state of the variables if needed + if (options.hidden !== undefined || options.physics !== undefined || dataChanged === true) { + this.body.emitter.emit('_dataChanged'); + } + } + } + }, { + key: 'setData', - /** - * get group options 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 options - */ - value: function get(groupname) { - var group = this.groups[groupname]; - if (group === undefined) { - if (this.options.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 % this.defaultGroups.length; - this.defaultIndex++; - group = {}; - group.color = this.defaultGroups[index]; - this.groups[groupname] = group; + /** + * Load edges by reading the data table + * @param {Array | DataSet | DataView} edges The data containing the edges. + * @private + * @private + */ + value: function setData(edges) { + var _this2 = this; + + var doNotEmit = arguments[1] === undefined ? false : arguments[1]; + + var oldEdgesData = this.body.data.edges; + + if (edges instanceof DataSet || edges instanceof DataView) { + this.body.data.edges = edges; + } else if (Array.isArray(edges)) { + this.body.data.edges = new DataSet(); + this.body.data.edges.add(edges); + } else if (!edges) { + this.body.data.edges = new DataSet(); + } else { + throw new TypeError('Array or DataSet expected'); + } + + // TODO: is this null or undefined or false? + if (oldEdgesData) { + // unsubscribe from old dataset + util.forEach(this.edgesListeners, function (callback, event) { + oldEdgesData.off(event, callback); + }); + } + + // remove drawn edges + this.body.edges = {}; + + // TODO: is this null or undefined or false? + if (this.body.data.edges) { + // subscribe to new dataset + util.forEach(this.edgesListeners, function (callback, event) { + _this2.body.data.edges.on(event, callback); + }); + + // draw all new nodes + var ids = this.body.data.edges.getIds(); + this.add(ids, true); + } + + if (doNotEmit === false) { + this.body.emitter.emit('_dataChanged'); + } + } + }, { + key: 'add', + + /** + * Add edges + * @param {Number[] | String[]} ids + * @private + */ + value: function add(ids) { + var doNotEmit = arguments[1] === undefined ? false : arguments[1]; + + var edges = this.body.edges; + var edgesData = this.body.data.edges; + + for (var i = 0; i < ids.length; i++) { + var id = ids[i]; + + var oldEdge = edges[id]; + if (oldEdge) { + oldEdge.disconnect(); + } + + var data = edgesData.get(id, { showInternalIds: true }); + edges[id] = this.create(data); + } + + if (doNotEmit === false) { + this.body.emitter.emit('_dataChanged'); + } + } + }, { + key: 'update', + + /** + * Update existing edges, or create them when not yet existing + * @param {Number[] | String[]} ids + * @private + */ + value: function update(ids) { + var edges = this.body.edges; + var edgesData = this.body.data.edges; + var dataChanged = false; + for (var i = 0; i < ids.length; i++) { + var id = ids[i]; + var data = edgesData.get(id); + var edge = edges[id]; + if (edge === null) { + // update edge + edge.disconnect(); + dataChanged = edge.setOptions(data) || dataChanged; // if a support node is added, data can be changed. + edge.connect(); + } else { + // create edge + this.body.edges[id] = this.create(data); + dataChanged = true; + } + } + + if (dataChanged === true) { + this.body.emitter.emit('_dataChanged'); + } else { + this.body.emitter.emit('_dataUpdated'); + } + } + }, { + key: 'remove', + + /** + * Remove existing edges. Non existing ids will be ignored + * @param {Number[] | String[]} ids + * @private + */ + value: function remove(ids) { + var edges = this.body.edges; + for (var i = 0; i < ids.length; i++) { + var id = ids[i]; + var edge = edges[id]; + if (edge !== undefined) { + if (edge.via != null) { + delete this.body.supportNodes[edge.via.id]; } + edge.disconnect(); + delete edges[id]; } + } - return group; - }, - writable: true, - configurable: true - }, - add: { + this.body.emitter.emit('_dataChanged'); + } + }, { + key: 'create', + value: function create(properties) { + return new _Edge2['default'](properties, this.body, this.options); + } + }, { + key: 'markAllEdgesAsDirty', + value: function markAllEdgesAsDirty() { + for (var edgeId in this.body.edges) { + this.body.edges[edgeId].edgeType.colorDirty = true; + } + } + }, { + key: 'reconnectEdges', - /** - * Add a custom group style - * @param {String} groupName - * @param {Object} style An object containing borderColor, - * backgroundColor, etc. - * @return {Object} group The created group object - */ - value: function add(groupName, style) { - this.groups[groupName] = style; - this.groupsArray.push(groupName); - return style; - }, - writable: true, - configurable: true + /** + * Reconnect all edges + * @private + */ + value: function reconnectEdges() { + var id; + var nodes = this.body.nodes; + var edges = this.body.edges; + + for (id in nodes) { + if (nodes.hasOwnProperty(id)) { + nodes[id].edges = []; + } + } + + for (id in edges) { + if (edges.hasOwnProperty(id)) { + var edge = edges[id]; + edge.from = null; + edge.to = null; + edge.connect(); + } + } } - }); + }]); - return Groups; + return EdgesHandler; })(); - module.exports = Groups; - // 20:bright red + exports['default'] = EdgesHandler; + module.exports = exports['default']; /***/ }, -/* 51 */, -/* 52 */, -/* 53 */ +/* 52 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; - var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); - var BarnesHutSolver = _interopRequire(__webpack_require__(72)); + Object.defineProperty(exports, '__esModule', { + value: true + }); - var Repulsion = _interopRequire(__webpack_require__(73)); + var _BarnesHutSolver = __webpack_require__(70); - var HierarchicalRepulsion = _interopRequire(__webpack_require__(74)); + var _BarnesHutSolver2 = _interopRequireWildcard(_BarnesHutSolver); - var SpringSolver = _interopRequire(__webpack_require__(75)); + var _Repulsion = __webpack_require__(71); - var HierarchicalSpringSolver = _interopRequire(__webpack_require__(76)); + var _Repulsion2 = _interopRequireWildcard(_Repulsion); - var CentralGravitySolver = _interopRequire(__webpack_require__(77)); + var _HierarchicalRepulsion = __webpack_require__(72); - var util = __webpack_require__(1); + var _HierarchicalRepulsion2 = _interopRequireWildcard(_HierarchicalRepulsion); + + var _SpringSolver = __webpack_require__(73); + + var _SpringSolver2 = _interopRequireWildcard(_SpringSolver); + + var _HierarchicalSpringSolver = __webpack_require__(74); + + var _HierarchicalSpringSolver2 = _interopRequireWildcard(_HierarchicalSpringSolver); + + var _CentralGravitySolver = __webpack_require__(75); + + var _CentralGravitySolver2 = _interopRequireWildcard(_CentralGravitySolver); + var util = __webpack_require__(1); var PhysicsEngine = (function () { function PhysicsEngine(body) { var _this = this; + _classCallCheck(this, PhysicsEngine); this.body = body; @@ -19226,7 +19446,7 @@ return /******/ (function(modules) { // webpackBootstrap }, maxVelocity: 50, minVelocity: 0.1, // px/s - solver: "barnesHut", + solver: 'barnesHut', stabilization: { enabled: true, iterations: 1000, // maximum number of iteration to stabilize @@ -19238,468 +19458,438 @@ return /******/ (function(modules) { // webpackBootstrap }; util.extend(this.options, this.defaultOptions); - this.body.emitter.on("initPhysics", function () { + this.body.emitter.on('initPhysics', function () { _this.initPhysics(); }); - this.body.emitter.on("resetPhysics", function () { + this.body.emitter.on('resetPhysics', function () { _this.stopSimulation();_this.ready = false; }); - this.body.emitter.on("disablePhysics", function () { + this.body.emitter.on('disablePhysics', function () { _this.physicsEnabled = false;_this.stopSimulation(); }); - this.body.emitter.on("restorePhysics", function () { + this.body.emitter.on('restorePhysics', function () { _this.setOptions(_this.options); if (_this.ready === true) { _this.stabilized = false; _this.runSimulation(); } }); - this.body.emitter.on("startSimulation", function () { + this.body.emitter.on('startSimulation', function () { if (_this.ready === true) { _this.stabilized = false; _this.runSimulation(); } }); - this.body.emitter.on("stopSimulation", function () { + this.body.emitter.on('stopSimulation', function () { _this.stopSimulation(); }); } - _prototypeProperties(PhysicsEngine, null, { - setOptions: { - value: function setOptions(options) { - if (options === false) { - this.physicsEnabled = false; - this.stopSimulation(); - } else { - this.physicsEnabled = true; - if (options !== undefined) { - util.selectiveNotDeepExtend(["stabilization"], this.options, options); - util.mergeOptions(this.options, options, "stabilization"); - } - this.init(); - } - }, - writable: true, - configurable: true - }, - init: { - value: function init() { - var options; - if (this.options.solver === "repulsion") { - options = this.options.repulsion; - this.nodesSolver = new Repulsion(this.body, this.physicsBody, options); - this.edgesSolver = new SpringSolver(this.body, this.physicsBody, options); - } else if (this.options.solver === "hierarchicalRepulsion") { - options = this.options.hierarchicalRepulsion; - this.nodesSolver = new HierarchicalRepulsion(this.body, this.physicsBody, options); - this.edgesSolver = new HierarchicalSpringSolver(this.body, this.physicsBody, options); - } else { - // barnesHut - options = this.options.barnesHut; - this.nodesSolver = new BarnesHutSolver(this.body, this.physicsBody, options); - this.edgesSolver = new SpringSolver(this.body, this.physicsBody, options); + _createClass(PhysicsEngine, [{ + key: 'setOptions', + value: function setOptions(options) { + if (options === false) { + this.physicsEnabled = false; + this.stopSimulation(); + } else { + this.physicsEnabled = true; + if (options !== undefined) { + util.selectiveNotDeepExtend(['stabilization'], this.options, options); + util.mergeOptions(this.options, options, 'stabilization'); } + this.init(); + } + } + }, { + key: 'init', + value: function init() { + var options; + if (this.options.solver === 'repulsion') { + options = this.options.repulsion; + this.nodesSolver = new _Repulsion2['default'](this.body, this.physicsBody, options); + this.edgesSolver = new _SpringSolver2['default'](this.body, this.physicsBody, options); + } else if (this.options.solver === 'hierarchicalRepulsion') { + options = this.options.hierarchicalRepulsion; + this.nodesSolver = new _HierarchicalRepulsion2['default'](this.body, this.physicsBody, options); + this.edgesSolver = new _HierarchicalSpringSolver2['default'](this.body, this.physicsBody, options); + } else { + // barnesHut + options = this.options.barnesHut; + this.nodesSolver = new _BarnesHutSolver2['default'](this.body, this.physicsBody, options); + this.edgesSolver = new _SpringSolver2['default'](this.body, this.physicsBody, options); + } - this.gravitySolver = new CentralGravitySolver(this.body, this.physicsBody, options); - this.modelOptions = options; - }, - writable: true, - configurable: true - }, - initPhysics: { - value: function initPhysics() { - if (this.physicsEnabled === true) { - this.stabilized = false; - if (this.options.stabilization.enabled === true) { - this.body.emitter.emit("_blockRedrawRequests"); - this.stabilize(); - } else { - this.ready = true; - this.body.emitter.emit("zoomExtent", { duration: 0 }, true); - this.runSimulation(); - } + this.gravitySolver = new _CentralGravitySolver2['default'](this.body, this.physicsBody, options); + this.modelOptions = options; + } + }, { + key: 'initPhysics', + value: function initPhysics() { + if (this.physicsEnabled === true) { + this.stabilized = false; + if (this.options.stabilization.enabled === true) { + this.body.emitter.emit('_blockRedrawRequests'); + this.stabilize(); } else { this.ready = true; - this.body.emitter.emit("_redraw"); - } - }, - writable: true, - configurable: true - }, - stopSimulation: { - value: function stopSimulation() { - this.stabilized = true; - if (this.viewFunction !== undefined) { - this.body.emitter.off("initRedraw", this.viewFunction); - this.viewFunction = undefined; - this.body.emitter.emit("_stopRendering"); + this.body.emitter.emit('zoomExtent', { duration: 0 }, true); + this.runSimulation(); } - }, - writable: true, - configurable: true - }, - runSimulation: { - value: function runSimulation() { - if (this.physicsEnabled === true) { - if (this.viewFunction === undefined) { - this.viewFunction = this.simulationStep.bind(this); - this.body.emitter.on("initRedraw", this.viewFunction); - this.body.emitter.emit("_startRendering"); - } - } else { - this.body.emitter.emit("_redraw"); + } else { + this.ready = true; + this.body.emitter.emit('_redraw'); + } + } + }, { + key: 'stopSimulation', + value: function stopSimulation() { + this.stabilized = true; + if (this.viewFunction !== undefined) { + this.body.emitter.off('initRedraw', this.viewFunction); + this.viewFunction = undefined; + this.body.emitter.emit('_stopRendering'); + } + } + }, { + key: 'runSimulation', + value: function runSimulation() { + if (this.physicsEnabled === true) { + if (this.viewFunction === undefined) { + this.viewFunction = this.simulationStep.bind(this); + this.body.emitter.on('initRedraw', this.viewFunction); + this.body.emitter.emit('_startRendering'); } - }, - writable: true, - configurable: true - }, - simulationStep: { - value: function simulationStep() { - // check if the physics have settled - var startTime = Date.now(); + } else { + this.body.emitter.emit('_redraw'); + } + } + }, { + key: 'simulationStep', + value: function simulationStep() { + // check if the physics have settled + var startTime = Date.now(); + this.physicsTick(); + var physicsTime = Date.now() - startTime; + + // run double speed if it is a little graph + if ((physicsTime < 0.4 * this.simulationInterval || this.runDoubleSpeed === true) && this.stabilized === false) { this.physicsTick(); - var physicsTime = Date.now() - startTime; - // run double speed if it is a little graph - if ((physicsTime < 0.4 * this.simulationInterval || this.runDoubleSpeed === true) && this.stabilized === false) { - this.physicsTick(); + // this makes sure there is no jitter. The decision is taken once to run it at double speed. + this.runDoubleSpeed = true; + } - // this makes sure there is no jitter. The decision is taken once to run it at double speed. - this.runDoubleSpeed = true; + if (this.stabilized === true) { + if (this.stabilizationIterations > 1) { + // trigger the 'stabilized' event. + // The event is triggered on the next tick, to prevent the case that + // it is fired while initializing the Network, in which case you would not + // be able to catch it + var me = this; + var params = { + iterations: this.stabilizationIterations + }; + this.stabilizationIterations = 0; + this.startedStabilization = false; + setTimeout(function () { + me.body.emitter.emit('stabilized', params); + }, 0); + } else { + this.stabilizationIterations = 0; } + this.stopSimulation(); + } + } + }, { + key: 'physicsTick', - if (this.stabilized === true) { - if (this.stabilizationIterations > 1) { - // trigger the 'stabilized' event. - // The event is triggered on the next tick, to prevent the case that - // it is fired while initializing the Network, in which case you would not - // be able to catch it - var me = this; - var params = { - iterations: this.stabilizationIterations - }; - this.stabilizationIterations = 0; - this.startedStabilization = false; - setTimeout(function () { - me.body.emitter.emit("stabilized", params); - }, 0); - } else { - this.stabilizationIterations = 0; - } - this.stopSimulation(); - } - }, - writable: true, - configurable: true - }, - physicsTick: { + /** + * A single simulation step (or 'tick') in the physics simulation + * + * @private + */ + value: function physicsTick() { + if (this.stabilized === false) { + this.calculateForces(); + this.stabilized = this.moveNodes(); - /** - * A single simulation step (or 'tick') in the physics simulation - * - * @private - */ - value: function physicsTick() { - if (this.stabilized === false) { - this.calculateForces(); - this.stabilized = this.moveNodes(); - - // determine if the network has stabilzied - if (this.stabilized === true) { - this.revert(); - } else { - // this is here to ensure that there is no start event when the network is already stable. - if (this.startedStabilization === false) { - this.body.emitter.emit("startStabilizing"); - this.startedStabilization = true; - } + // determine if the network has stabilzied + if (this.stabilized === true) { + this.revert(); + } else { + // this is here to ensure that there is no start event when the network is already stable. + if (this.startedStabilization === false) { + this.body.emitter.emit('startStabilizing'); + this.startedStabilization = true; } - - this.stabilizationIterations++; } - }, - writable: true, - configurable: true - }, - updatePhysicsIndices: { - /** - * 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.body.nodes with the support nodes. - * - * @private - */ - value: function updatePhysicsIndices() { - this.physicsBody.forces = {}; - this.physicsBody.physicsNodeIndices = []; - this.physicsBody.physicsEdgeIndices = []; - var nodes = this.body.nodes; - var edges = this.body.edges; + this.stabilizationIterations++; + } + } + }, { + key: 'updatePhysicsIndices', - // get node indices for physics - for (var nodeId in nodes) { - if (nodes.hasOwnProperty(nodeId)) { - if (nodes[nodeId].options.physics === true) { - this.physicsBody.physicsNodeIndices.push(nodeId); - } + /** + * 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.body.nodes with the support nodes. + * + * @private + */ + value: function updatePhysicsIndices() { + this.physicsBody.forces = {}; + this.physicsBody.physicsNodeIndices = []; + this.physicsBody.physicsEdgeIndices = []; + var nodes = this.body.nodes; + var edges = this.body.edges; + + // get node indices for physics + for (var nodeId in nodes) { + if (nodes.hasOwnProperty(nodeId)) { + if (nodes[nodeId].options.physics === true) { + this.physicsBody.physicsNodeIndices.push(nodeId); } } + } - // get edge indices for physics - for (var edgeId in edges) { - if (edges.hasOwnProperty(edgeId)) { - if (edges[edgeId].options.physics === true) { - this.physicsBody.physicsEdgeIndices.push(edgeId); - } + // get edge indices for physics + for (var edgeId in edges) { + if (edges.hasOwnProperty(edgeId)) { + if (edges[edgeId].options.physics === true) { + this.physicsBody.physicsEdgeIndices.push(edgeId); } } + } - // get the velocity and the forces vector - for (var i = 0; i < this.physicsBody.physicsNodeIndices.length; i++) { - var nodeId = this.physicsBody.physicsNodeIndices[i]; - this.physicsBody.forces[nodeId] = { x: 0, y: 0 }; - - // forces can be reset because they are recalculated. Velocities have to persist. - if (this.physicsBody.velocities[nodeId] === undefined) { - this.physicsBody.velocities[nodeId] = { x: 0, y: 0 }; - } - } + // get the velocity and the forces vector + for (var i = 0; i < this.physicsBody.physicsNodeIndices.length; i++) { + var nodeId = this.physicsBody.physicsNodeIndices[i]; + this.physicsBody.forces[nodeId] = { x: 0, y: 0 }; - // clean deleted nodes from the velocity vector - for (var nodeId in this.physicsBody.velocities) { - if (nodes[nodeId] === undefined) { - delete this.physicsBody.velocities[nodeId]; - } - } - }, - writable: true, - configurable: true - }, - revert: { - value: function revert() { - var nodeIds = Object.keys(this.previousStates); - var nodes = this.body.nodes; - var velocities = this.physicsBody.velocities; - - for (var i = 0; i < nodeIds.length; i++) { - var nodeId = nodeIds[i]; - if (nodes[nodeId] !== undefined) { - if (nodes[nodeId].options.physics === true) { - velocities[nodeId].x = this.previousStates[nodeId].vx; - velocities[nodeId].y = this.previousStates[nodeId].vy; - nodes[nodeId].x = this.previousStates[nodeId].x; - nodes[nodeId].y = this.previousStates[nodeId].y; - } - } else { - delete this.previousStates[nodeId]; - } + // forces can be reset because they are recalculated. Velocities have to persist. + if (this.physicsBody.velocities[nodeId] === undefined) { + this.physicsBody.velocities[nodeId] = { x: 0, y: 0 }; } - }, - writable: true, - configurable: true - }, - moveNodes: { - value: function moveNodes() { - var nodesPresent = false; - var nodeIndices = this.physicsBody.physicsNodeIndices; - var maxVelocity = this.options.maxVelocity === 0 ? 1000000000 : this.options.maxVelocity; - var stabilized = true; - var vminCorrected = this.options.minVelocity / Math.max(this.body.view.scale, 0.05); + } - for (var i = 0; i < nodeIndices.length; i++) { - var nodeId = nodeIndices[i]; - var nodeVelocity = this._performStep(nodeId, maxVelocity); - // stabilized is true if stabilized is true and velocity is smaller than vmin --> all nodes must be stabilized - stabilized = nodeVelocity < vminCorrected && stabilized === true; - nodesPresent = true; + // clean deleted nodes from the velocity vector + for (var nodeId in this.physicsBody.velocities) { + if (nodes[nodeId] === undefined) { + delete this.physicsBody.velocities[nodeId]; } - - - if (nodesPresent === true) { - if (vminCorrected > 0.5 * this.options.maxVelocity) { - return false; - } else { - return stabilized; + } + } + }, { + key: 'revert', + value: function revert() { + var nodeIds = Object.keys(this.previousStates); + var nodes = this.body.nodes; + var velocities = this.physicsBody.velocities; + + for (var i = 0; i < nodeIds.length; i++) { + var nodeId = nodeIds[i]; + if (nodes[nodeId] !== undefined) { + if (nodes[nodeId].options.physics === true) { + velocities[nodeId].x = this.previousStates[nodeId].vx; + velocities[nodeId].y = this.previousStates[nodeId].vy; + nodes[nodeId].x = this.previousStates[nodeId].x; + nodes[nodeId].y = this.previousStates[nodeId].y; } - } - return true; - }, - writable: true, - configurable: true - }, - _performStep: { - value: function _performStep(nodeId, maxVelocity) { - var node = this.body.nodes[nodeId]; - var timestep = this.options.timestep; - var forces = this.physicsBody.forces; - var velocities = this.physicsBody.velocities; - - // store the state so we can revert - this.previousStates[nodeId] = { x: node.x, y: node.y, vx: velocities[nodeId].x, vy: velocities[nodeId].y }; - - if (node.options.fixed.x === false) { - var dx = this.modelOptions.damping * velocities[nodeId].x; // damping force - var ax = (forces[nodeId].x - dx) / node.options.mass; // acceleration - velocities[nodeId].x += ax * timestep; // velocity - velocities[nodeId].x = Math.abs(velocities[nodeId].x) > maxVelocity ? velocities[nodeId].x > 0 ? maxVelocity : -maxVelocity : velocities[nodeId].x; - node.x += velocities[nodeId].x * timestep; // position } else { - forces[nodeId].x = 0; - velocities[nodeId].x = 0; + delete this.previousStates[nodeId]; } + } + } + }, { + key: 'moveNodes', + value: function moveNodes() { + var nodesPresent = false; + var nodeIndices = this.physicsBody.physicsNodeIndices; + var maxVelocity = this.options.maxVelocity === 0 ? 1000000000 : this.options.maxVelocity; + var stabilized = true; + var vminCorrected = this.options.minVelocity / Math.max(this.body.view.scale, 0.05); + + for (var i = 0; i < nodeIndices.length; i++) { + var nodeId = nodeIndices[i]; + var nodeVelocity = this._performStep(nodeId, maxVelocity); + // stabilized is true if stabilized is true and velocity is smaller than vmin --> all nodes must be stabilized + stabilized = nodeVelocity < vminCorrected && stabilized === true; + nodesPresent = true; + } - if (node.options.fixed.y === false) { - var dy = this.modelOptions.damping * velocities[nodeId].y; // damping force - var ay = (forces[nodeId].y - dy) / node.options.mass; // acceleration - velocities[nodeId].y += ay * timestep; // velocity - velocities[nodeId].y = Math.abs(velocities[nodeId].y) > maxVelocity ? velocities[nodeId].y > 0 ? maxVelocity : -maxVelocity : velocities[nodeId].y; - node.y += velocities[nodeId].y * timestep; // position + if (nodesPresent === true) { + if (vminCorrected > 0.5 * this.options.maxVelocity) { + return false; } else { - forces[nodeId].y = 0; - velocities[nodeId].y = 0; + return stabilized; } + } + return true; + } + }, { + key: '_performStep', + value: function _performStep(nodeId, maxVelocity) { + var node = this.body.nodes[nodeId]; + var timestep = this.options.timestep; + var forces = this.physicsBody.forces; + var velocities = this.physicsBody.velocities; + + // store the state so we can revert + this.previousStates[nodeId] = { x: node.x, y: node.y, vx: velocities[nodeId].x, vy: velocities[nodeId].y }; + + if (node.options.fixed.x === false) { + var dx = this.modelOptions.damping * velocities[nodeId].x; // damping force + var ax = (forces[nodeId].x - dx) / node.options.mass; // acceleration + velocities[nodeId].x += ax * timestep; // velocity + velocities[nodeId].x = Math.abs(velocities[nodeId].x) > maxVelocity ? velocities[nodeId].x > 0 ? maxVelocity : -maxVelocity : velocities[nodeId].x; + node.x += velocities[nodeId].x * timestep; // position + } else { + forces[nodeId].x = 0; + velocities[nodeId].x = 0; + } - var totalVelocity = Math.sqrt(Math.pow(velocities[nodeId].x, 2) + Math.pow(velocities[nodeId].y, 2)); - return totalVelocity; - }, - writable: true, - configurable: true - }, - calculateForces: { - value: function calculateForces() { - this.gravitySolver.solve(); - this.nodesSolver.solve(); - this.edgesSolver.solve(); - }, - writable: true, - configurable: true - }, - _freezeNodes: { - + if (node.options.fixed.y === false) { + var dy = this.modelOptions.damping * velocities[nodeId].y; // damping force + var ay = (forces[nodeId].y - dy) / node.options.mass; // acceleration + velocities[nodeId].y += ay * timestep; // velocity + velocities[nodeId].y = Math.abs(velocities[nodeId].y) > maxVelocity ? velocities[nodeId].y > 0 ? maxVelocity : -maxVelocity : velocities[nodeId].y; + node.y += velocities[nodeId].y * timestep; // position + } else { + forces[nodeId].y = 0; + velocities[nodeId].y = 0; + } + var totalVelocity = Math.sqrt(Math.pow(velocities[nodeId].x, 2) + Math.pow(velocities[nodeId].y, 2)); + return totalVelocity; + } + }, { + key: 'calculateForces', + value: function calculateForces() { + this.gravitySolver.solve(); + this.nodesSolver.solve(); + this.edgesSolver.solve(); + } + }, { + key: '_freezeNodes', - /** - * When initializing and stabilizing, we can freeze nodes with a predefined position. This greatly speeds up stabilization - * because only the supportnodes for the smoothCurves have to settle. - * - * @private - */ - value: function _freezeNodes() { - var nodes = this.body.nodes; - for (var id in nodes) { - if (nodes.hasOwnProperty(id)) { - if (nodes[id].x && nodes[id].y) { - this.freezeCache[id] = { x: nodes[id].options.fixed.x, y: nodes[id].options.fixed.y }; - nodes[id].options.fixed.x = true; - nodes[id].options.fixed.y = true; - } + /** + * When initializing and stabilizing, we can freeze nodes with a predefined position. This greatly speeds up stabilization + * because only the supportnodes for the smoothCurves have to settle. + * + * @private + */ + value: function _freezeNodes() { + var nodes = this.body.nodes; + for (var id in nodes) { + if (nodes.hasOwnProperty(id)) { + if (nodes[id].x && nodes[id].y) { + this.freezeCache[id] = { x: nodes[id].options.fixed.x, y: nodes[id].options.fixed.y }; + nodes[id].options.fixed.x = true; + nodes[id].options.fixed.y = true; } } - }, - writable: true, - configurable: true - }, - _restoreFrozenNodes: { + } + } + }, { + key: '_restoreFrozenNodes', - /** - * Unfreezes the nodes that have been frozen by _freezeDefinedNodes. - * - * @private - */ - value: function _restoreFrozenNodes() { - var nodes = this.body.nodes; - for (var id in nodes) { - if (nodes.hasOwnProperty(id)) { - if (this.freezeCache[id] !== undefined) { - nodes[id].options.fixed.x = this.freezeCache[id].x; - nodes[id].options.fixed.y = this.freezeCache[id].y; - } + /** + * Unfreezes the nodes that have been frozen by _freezeDefinedNodes. + * + * @private + */ + value: function _restoreFrozenNodes() { + var nodes = this.body.nodes; + for (var id in nodes) { + if (nodes.hasOwnProperty(id)) { + if (this.freezeCache[id] !== undefined) { + nodes[id].options.fixed.x = this.freezeCache[id].x; + nodes[id].options.fixed.y = this.freezeCache[id].y; } } - this.freezeCache = {}; - }, - writable: true, - configurable: true - }, - stabilize: { + } + this.freezeCache = {}; + } + }, { + key: 'stabilize', - /** - * Find a stable position for all nodes - * @private - */ - value: function stabilize() { - if (this.options.stabilization.onlyDynamicEdges === true) { - this._freezeNodes(); - } - this.stabilizationSteps = 0; + /** + * Find a stable position for all nodes + * @private + */ + value: function stabilize() { + if (this.options.stabilization.onlyDynamicEdges === true) { + this._freezeNodes(); + } + this.stabilizationSteps = 0; + + setTimeout(this._stabilizationBatch.bind(this), 0); + } + }, { + key: '_stabilizationBatch', + value: function _stabilizationBatch() { + var count = 0; + while (this.stabilized === false && count < this.options.stabilization.updateInterval && this.stabilizationSteps < this.options.stabilization.iterations) { + this.physicsTick(); + this.stabilizationSteps++; + count++; + } + if (this.stabilized === false && this.stabilizationSteps < this.options.stabilization.iterations) { + this.body.emitter.emit('stabilizationProgress', { steps: this.stabilizationSteps, total: this.options.stabilization.iterations }); setTimeout(this._stabilizationBatch.bind(this), 0); - }, - writable: true, - configurable: true - }, - _stabilizationBatch: { - value: function _stabilizationBatch() { - var count = 0; - while (this.stabilized === false && count < this.options.stabilization.updateInterval && this.stabilizationSteps < this.options.stabilization.iterations) { - this.physicsTick(); - this.stabilizationSteps++; - count++; - } - - if (this.stabilized === false && this.stabilizationSteps < this.options.stabilization.iterations) { - this.body.emitter.emit("stabilizationProgress", { steps: this.stabilizationSteps, total: this.options.stabilization.iterations }); - setTimeout(this._stabilizationBatch.bind(this), 0); - } else { - this._finalizeStabilization(); - } - }, - writable: true, - configurable: true - }, - _finalizeStabilization: { - value: function _finalizeStabilization() { - this.body.emitter.emit("_allowRedrawRequests"); - if (this.options.stabilization.zoomExtent === true) { - this.body.emitter.emit("zoomExtent", { duration: 0 }); - } + } else { + this._finalizeStabilization(); + } + } + }, { + key: '_finalizeStabilization', + value: function _finalizeStabilization() { + this.body.emitter.emit('_allowRedrawRequests'); + if (this.options.stabilization.zoomExtent === true) { + this.body.emitter.emit('zoomExtent', { duration: 0 }); + } - if (this.options.stabilization.onlyDynamicEdges === true) { - this._restoreFrozenNodes(); - } + if (this.options.stabilization.onlyDynamicEdges === true) { + this._restoreFrozenNodes(); + } - this.body.emitter.emit("stabilizationIterationsDone"); - this.body.emitter.emit("_requestRedraw"); + this.body.emitter.emit('stabilizationIterationsDone'); + this.body.emitter.emit('_requestRedraw'); - this.ready = true; - }, - writable: true, - configurable: true + this.ready = true; } - }); + }]); return PhysicsEngine; })(); - module.exports = PhysicsEngine; + exports['default'] = PhysicsEngine; + module.exports = exports['default']; /***/ }, -/* 54 */ +/* 53 */ /***/ function(module, exports, __webpack_require__) { "use strict"; - var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; - - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { "default": obj }; }; var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + Object.defineProperty(exports, "__esModule", { + value: true + }); + + var _Cluster = __webpack_require__(76); + + var _Cluster2 = _interopRequireWildcard(_Cluster); + var util = __webpack_require__(1); - var Cluster = _interopRequire(__webpack_require__(100)); var ClusterEngine = (function () { function ClusterEngine(body) { @@ -19713,685 +19903,956 @@ return /******/ (function(modules) { // webpackBootstrap util.extend(this.options, this.defaultOptions); } - _prototypeProperties(ClusterEngine, null, { - setOptions: { - value: function setOptions(options) { - if (options !== undefined) {} - }, - writable: true, - configurable: true - }, - clusterByConnectionCount: { + _createClass(ClusterEngine, [{ + key: "setOptions", + value: function setOptions(options) { + if (options !== undefined) {} + } + }, { + key: "clusterByConnectionCount", - /** - * - * @param hubsize - * @param options - */ - value: function clusterByConnectionCount(hubsize, options) { - if (hubsize === undefined) { - hubsize = this._getHubSize(); - } else if (tyepof(hubsize) === "object") { - options = this._checkOptions(hubsize); - hubsize = this._getHubSize(); - } - - var nodesToCluster = []; - for (var i = 0; i < this.body.nodeIndices.length; i++) { - var node = this.body.nodes[this.body.nodeIndices[i]]; - if (node.edges.length >= hubsize) { - nodesToCluster.push(node.id); - } - } + /** + * + * @param hubsize + * @param options + */ + value: function clusterByConnectionCount(hubsize, options) { + if (hubsize === undefined) { + hubsize = this._getHubSize(); + } else if (tyepof(hubsize) === "object") { + options = this._checkOptions(hubsize); + hubsize = this._getHubSize(); + } - for (var i = 0; i < nodesToCluster.length; i++) { - var node = this.body.nodes[nodesToCluster[i]]; - this.clusterByConnection(node, options, {}, {}, false); + var nodesToCluster = []; + for (var i = 0; i < this.body.nodeIndices.length; i++) { + var node = this.body.nodes[this.body.nodeIndices[i]]; + if (node.edges.length >= hubsize) { + nodesToCluster.push(node.id); } - this.body.emitter.emit("_dataChanged"); - }, - writable: true, - configurable: true - }, - clusterByNodeData: { + } + for (var i = 0; i < nodesToCluster.length; i++) { + var node = this.body.nodes[nodesToCluster[i]]; + this.clusterByConnection(node, options, {}, {}, false); + } + this.body.emitter.emit("_dataChanged"); + } + }, { + key: "clusterByNodeData", - /** - * loop over all nodes, check if they adhere to the condition and cluster if needed. - * @param options - * @param refreshData - */ - value: function clusterByNodeData() { - var options = arguments[0] === undefined ? {} : arguments[0]; - var refreshData = arguments[1] === undefined ? true : arguments[1]; - if (options.joinCondition === undefined) { - throw new Error("Cannot call clusterByNodeData without a joinCondition function in the options."); - } + /** + * loop over all nodes, check if they adhere to the condition and cluster if needed. + * @param options + * @param refreshData + */ + value: function clusterByNodeData() { + var options = arguments[0] === undefined ? {} : arguments[0]; + var refreshData = arguments[1] === undefined ? true : arguments[1]; + + if (options.joinCondition === undefined) { + throw new Error("Cannot call clusterByNodeData without a joinCondition function in the options."); + } - // check if the options object is fine, append if needed - options = this._checkOptions(options); + // check if the options object is fine, append if needed + options = this._checkOptions(options); - var childNodesObj = {}; - var childEdgesObj = {}; + var childNodesObj = {}; + var childEdgesObj = {}; - // collect the nodes that will be in the cluster - for (var i = 0; i < this.body.nodeIndices.length; i++) { - var nodeId = this.body.nodeIndices[i]; - var clonedOptions = this._cloneOptions(nodeId); - if (options.joinCondition(clonedOptions) === true) { - childNodesObj[nodeId] = this.body.nodes[nodeId]; - } + // collect the nodes that will be in the cluster + for (var i = 0; i < this.body.nodeIndices.length; i++) { + var nodeId = this.body.nodeIndices[i]; + var clonedOptions = this._cloneOptions(nodeId); + if (options.joinCondition(clonedOptions) === true) { + childNodesObj[nodeId] = this.body.nodes[nodeId]; } + } - this._cluster(childNodesObj, childEdgesObj, options, refreshData); - }, - writable: true, - configurable: true - }, - clusterOutliers: { - + this._cluster(childNodesObj, childEdgesObj, options, refreshData); + } + }, { + key: "clusterOutliers", - /** - * Cluster all nodes in the network that have only 1 edge - * @param options - * @param refreshData - */ - value: function clusterOutliers(options) { - var refreshData = arguments[1] === undefined ? true : arguments[1]; - options = this._checkOptions(options); - var clusters = []; - - // collect the nodes that will be in the cluster - for (var i = 0; i < this.body.nodeIndices.length; i++) { - var childNodesObj = {}; - var childEdgesObj = {}; - var nodeId = this.body.nodeIndices[i]; - if (this.body.nodes[nodeId].edges.length === 1) { - var edge = this.body.nodes[nodeId].edges[0]; - var childNodeId = this._getConnectedId(edge, nodeId); - if (childNodeId != nodeId) { - if (options.joinCondition === undefined) { + /** + * Cluster all nodes in the network that have only 1 edge + * @param options + * @param refreshData + */ + value: function clusterOutliers(options) { + var refreshData = arguments[1] === undefined ? true : arguments[1]; + + options = this._checkOptions(options); + var clusters = []; + + // collect the nodes that will be in the cluster + for (var i = 0; i < this.body.nodeIndices.length; i++) { + var childNodesObj = {}; + var childEdgesObj = {}; + var nodeId = this.body.nodeIndices[i]; + if (this.body.nodes[nodeId].edges.length === 1) { + var edge = this.body.nodes[nodeId].edges[0]; + var childNodeId = this._getConnectedId(edge, nodeId); + if (childNodeId != nodeId) { + if (options.joinCondition === undefined) { + childNodesObj[nodeId] = this.body.nodes[nodeId]; + childNodesObj[childNodeId] = this.body.nodes[childNodeId]; + } else { + var clonedOptions = this._cloneOptions(nodeId); + if (options.joinCondition(clonedOptions) === true) { childNodesObj[nodeId] = this.body.nodes[nodeId]; + } + clonedOptions = this._cloneOptions(childNodeId); + if (options.joinCondition(clonedOptions) === true) { childNodesObj[childNodeId] = this.body.nodes[childNodeId]; - } else { - var clonedOptions = this._cloneOptions(nodeId); - if (options.joinCondition(clonedOptions) === true) { - childNodesObj[nodeId] = this.body.nodes[nodeId]; - } - clonedOptions = this._cloneOptions(childNodeId); - if (options.joinCondition(clonedOptions) === true) { - childNodesObj[childNodeId] = this.body.nodes[childNodeId]; - } } - clusters.push({ nodes: childNodesObj, edges: childEdgesObj }); } + clusters.push({ nodes: childNodesObj, edges: childEdgesObj }); } } + } - for (var i = 0; i < clusters.length; i++) { - this._cluster(clusters[i].nodes, clusters[i].edges, options, false); - } - - if (refreshData === true) { - this.body.emitter.emit("_dataChanged"); - } - }, - writable: true, - configurable: true - }, - clusterByConnection: { + for (var i = 0; i < clusters.length; i++) { + this._cluster(clusters[i].nodes, clusters[i].edges, options, false); + } - /** - * - * @param nodeId - * @param options - * @param refreshData - */ - value: function clusterByConnection(nodeId, options) { - var refreshData = arguments[2] === undefined ? true : arguments[2]; - // kill conditions - if (nodeId === undefined) { - throw new Error("No nodeId supplied to clusterByConnection!"); - } - if (this.body.nodes[nodeId] === undefined) { - throw new Error("The nodeId given to clusterByConnection does not exist!"); - } + if (refreshData === true) { + this.body.emitter.emit("_dataChanged"); + } + } + }, { + key: "clusterByConnection", - var node = this.body.nodes[nodeId]; - options = this._checkOptions(options, node); - if (options.clusterNodeProperties.x === undefined) { - options.clusterNodeProperties.x = node.x; - } - if (options.clusterNodeProperties.y === undefined) { - options.clusterNodeProperties.y = node.y; - } - if (options.clusterNodeProperties.fixed === undefined) { - options.clusterNodeProperties.fixed = {}; - options.clusterNodeProperties.fixed.x = node.options.fixed.x; - options.clusterNodeProperties.fixed.y = node.options.fixed.y; - } + /** + * + * @param nodeId + * @param options + * @param refreshData + */ + value: function clusterByConnection(nodeId, options) { + var refreshData = arguments[2] === undefined ? true : arguments[2]; + + // kill conditions + if (nodeId === undefined) { + throw new Error("No nodeId supplied to clusterByConnection!"); + } + if (this.body.nodes[nodeId] === undefined) { + throw new Error("The nodeId given to clusterByConnection does not exist!"); + } + var node = this.body.nodes[nodeId]; + options = this._checkOptions(options, node); + if (options.clusterNodeProperties.x === undefined) { + options.clusterNodeProperties.x = node.x; + } + if (options.clusterNodeProperties.y === undefined) { + options.clusterNodeProperties.y = node.y; + } + if (options.clusterNodeProperties.fixed === undefined) { + options.clusterNodeProperties.fixed = {}; + options.clusterNodeProperties.fixed.x = node.options.fixed.x; + options.clusterNodeProperties.fixed.y = node.options.fixed.y; + } - var childNodesObj = {}; - var childEdgesObj = {}; - var parentNodeId = node.id; - var parentClonedOptions = this._cloneOptions(parentNodeId); - childNodesObj[parentNodeId] = node; + var childNodesObj = {}; + var childEdgesObj = {}; + 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++) { - var edge = node.edges[i]; - var childNodeId = this._getConnectedId(edge, parentNodeId); + // collect the nodes that will be in the cluster + for (var i = 0; i < node.edges.length; i++) { + var edge = node.edges[i]; + var childNodeId = this._getConnectedId(edge, parentNodeId); - if (childNodeId !== parentNodeId) { - if (options.joinCondition === undefined) { + if (childNodeId !== parentNodeId) { + if (options.joinCondition === undefined) { + childEdgesObj[edge.id] = edge; + childNodesObj[childNodeId] = this.body.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.body.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.body.nodes[childNodeId]; - } } - } else { - childEdgesObj[edge.id] = edge; } - } - - this._cluster(childNodesObj, childEdgesObj, options, refreshData); - }, - writable: true, - configurable: true - }, - _cloneOptions: { - - - /** - * This returns a clone of the options or options of the edge or node to be used for construction of new edges or check functions for new nodes. - * @param objId - * @param type - * @returns {{}} - * @private - */ - value: function _cloneOptions(objId, type) { - var clonedOptions = {}; - if (type === undefined || type === "node") { - util.deepExtend(clonedOptions, this.body.nodes[objId].options, true); - util.deepExtend(clonedOptions, this.body.nodes[objId].properties, true); - clonedOptions.amountOfConnections = this.body.nodes[objId].edges.length; } else { - util.deepExtend(clonedOptions, this.body.edges[objId].properties, true); + childEdgesObj[edge.id] = edge; } - return clonedOptions; - }, - writable: true, - configurable: true - }, - _createClusterEdges: { + } + this._cluster(childNodesObj, childEdgesObj, options, refreshData); + } + }, { + key: "_cloneOptions", - /** - * This function creates the edges that will be attached to the cluster. - * - * @param childNodesObj - * @param childEdgesObj - * @param newEdges - * @param options - * @private - */ - value: function _createClusterEdges(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; + /** + * This returns a clone of the options or options of the edge or node to be used for construction of new edges or check functions for new nodes. + * @param objId + * @param type + * @returns {{}} + * @private + */ + value: function _cloneOptions(objId, type) { + var clonedOptions = {}; + if (type === undefined || type === "node") { + util.deepExtend(clonedOptions, this.body.nodes[objId].options, true); + util.deepExtend(clonedOptions, this.body.nodes[objId].properties, true); + clonedOptions.amountOfConnections = this.body.nodes[objId].edges.length; + } else { + util.deepExtend(clonedOptions, this.body.edges[objId].properties, true); + } + return clonedOptions; + } + }, { + key: "_createClusterEdges", - 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; - } + /** + * This function creates the edges that will be attached to the cluster. + * + * @param childNodesObj + * @param childEdgesObj + * @param newEdges + * @param options + * @private + */ + value: function _createClusterEdges(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); - 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(this.body.functions.createEdge(clonedOptions)); + if (childNodesObj[otherNodeId] === undefined) { + var clonedOptions = this._cloneOptions(edge.id, "edge"); + util.deepExtend(clonedOptions, options.clusterEdgeProperties); + 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(this.body.functions.createEdge(clonedOptions)); } } - }, - writable: true, - configurable: true - }, - _checkOptions: { + } + } + }, { + key: "_checkOptions", + /** + * This function checks the options that can be supplied to the different cluster functions + * for certain fields and inserts defaults if needed + * @param options + * @returns {*} + * @private + */ + value: function _checkOptions() { + var options = arguments[0] === undefined ? {} : arguments[0]; + + if (options.clusterEdgeProperties === undefined) { + options.clusterEdgeProperties = {}; + } + if (options.clusterNodeProperties === undefined) { + options.clusterNodeProperties = {}; + } - /** - * This function checks the options that can be supplied to the different cluster functions - * for certain fields and inserts defaults if needed - * @param options - * @returns {*} - * @private - */ - value: function _checkOptions() { - var options = arguments[0] === undefined ? {} : arguments[0]; - if (options.clusterEdgeProperties === undefined) { - options.clusterEdgeProperties = {}; - } - if (options.clusterNodeProperties === undefined) { - options.clusterNodeProperties = {}; - } + return options; + } + }, { + key: "_cluster", - return options; - }, - writable: true, - configurable: true - }, - _cluster: { + /** + * + * @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} refreshData | when true, do not wrap up + * @private + */ + value: function _cluster(childNodesObj, childEdgesObj, options) { + var refreshData = arguments[3] === undefined ? true : arguments[3]; + + // kill condition: no children so cant cluster + if (Object.keys(childNodesObj).length === 0) { + return; + } - /** - * - * @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} refreshData | when true, do not wrap up - * @private - */ - value: function _cluster(childNodesObj, childEdgesObj, options) { - var refreshData = arguments[3] === undefined ? true : arguments[3]; - // 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); } - // check if we have an unique id; - if (options.clusterNodeProperties.id === undefined) { - options.clusterNodeProperties.id = "cluster:" + util.randomUUID(); + // get clusterproperties based on childNodes + var childEdgesOptions = []; + for (var edgeId in childEdgesObj) { + var clonedOptions = this._cloneOptions(edgeId, "edge"); + childEdgesOptions.push(clonedOptions); } - var clusterId = options.clusterNodeProperties.id; - // create the new edges that will connect to the cluster - var newEdges = []; - this._createClusterEdges(childNodesObj, childEdgesObj, newEdges, options); + 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"; + } - // 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); - } + // 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; + } + if (clusterNodeProperties.x === undefined) { + if (pos === undefined) { + pos = this._getClusterPosition(childNodesObj); + } + clusterNodeProperties.y = pos.y; + clusterNodeProperties.allowedToMoveY = true; + } - // get clusterproperties based on childNodes - var childEdgesOptions = []; - for (var edgeId in childEdgesObj) { - var clonedOptions = this._cloneOptions(edgeId, "edge"); - childEdgesOptions.push(clonedOptions); - } + // force the ID to remain the same + clusterNodeProperties.id = clusterId; - clusterNodeProperties = options.processProperties(clusterNodeProperties, childNodesOptions, childEdgesOptions); - if (!clusterNodeProperties) { - throw new Error("The processClusterProperties function does not return properties!"); + // create the clusterNode + var clusterNode = this.body.functions.createNode(clusterNodeProperties, _Cluster2["default"]); + clusterNode.isCluster = true; + clusterNode.containedNodes = childNodesObj; + clusterNode.containedEdges = childEdgesObj; + + // disable the childEdges + for (var edgeId in childEdgesObj) { + if (childEdgesObj.hasOwnProperty(edgeId)) { + if (this.body.edges[edgeId] !== undefined) { + var edge = this.body.edges[edgeId]; + edge.togglePhysics(false); + edge.options.hidden = true; } } - if (clusterNodeProperties.label === undefined) { - clusterNodeProperties.label = "cluster"; + } + + // disable the childNodes + for (var nodeId in childNodesObj) { + if (childNodesObj.hasOwnProperty(nodeId)) { + this.clusteredNodes[nodeId] = { clusterId: clusterNodeProperties.id, node: this.body.nodes[nodeId] }; + this.body.nodes[nodeId].togglePhysics(false); + this.body.nodes[nodeId].options.hidden = true; } + } + // finally put the cluster node into global + this.body.nodes[clusterNodeProperties.id] = clusterNode; - // 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; + // push new edges to global + for (var i = 0; i < newEdges.length; i++) { + this.body.edges[newEdges[i].id] = newEdges[i]; + this.body.edges[newEdges[i].id].connect(); + } + + // set ID to undefined so no duplicates arise + clusterNodeProperties.id = undefined; + + // wrap up + if (refreshData === true) { + this.body.emitter.emit("_dataChanged"); + } + } + }, { + key: "isCluster", + + /** + * Check if a node is a cluster. + * @param nodeId + * @returns {*} + */ + value: function isCluster(nodeId) { + if (this.body.nodes[nodeId] !== undefined) { + return this.body.nodes[nodeId].isCluster === true; + } else { + console.log("Node does not exist."); + return false; + } + } + }, { + key: "_getClusterPosition", + + /** + * 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 + */ + value: function _getClusterPosition(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) }; + } + }, { + key: "openCluster", + + /** + * Open a cluster by calling this function. + * @param {String} clusterNodeId | the ID of the cluster node + * @param {Boolean} refreshData | wrap up afterwards if not true + */ + value: function openCluster(clusterNodeId) { + var refreshData = arguments[1] === undefined ? true : arguments[1]; + + // kill conditions + if (clusterNodeId === undefined) { + throw new Error("No clusterNodeId supplied to openCluster."); + } + if (this.body.nodes[clusterNodeId] === undefined) { + throw new Error("The clusterNodeId supplied to openCluster does not exist."); + } + if (this.body.nodes[clusterNodeId].containedNodes === undefined) { + console.log("The node:" + clusterNodeId + " is not a cluster.");return; + }; + + var clusterNode = this.body.nodes[clusterNodeId]; + var containedNodes = clusterNode.containedNodes; + var containedEdges = clusterNode.containedEdges; + + // release nodes + for (var nodeId in containedNodes) { + if (containedNodes.hasOwnProperty(nodeId)) { + var containedNode = this.body.nodes[nodeId]; + containedNode = containedNodes[nodeId]; + // inherit position + containedNode.x = clusterNode.x; + containedNode.y = clusterNode.y; + + // inherit speed + containedNode.vx = clusterNode.vx; + containedNode.vy = clusterNode.vy; + + containedNode.options.hidden = false; + containedNode.togglePhysics(true); + + delete this.clusteredNodes[nodeId]; } - if (clusterNodeProperties.x === undefined) { - if (pos === undefined) { - pos = this._getClusterPosition(childNodesObj); - } - clusterNodeProperties.y = pos.y; - clusterNodeProperties.allowedToMoveY = true; + } + + // release edges + for (var edgeId in containedEdges) { + if (containedEdges.hasOwnProperty(edgeId)) { + var edge = this.body.edges[edgeId]; + edge.options.hidden = false; + edge.togglePhysics(true); } + } + // remove all temporary edges + for (var i = 0; i < clusterNode.edges.length; i++) { + var edgeId = clusterNode.edges[i].id; + var viaId = this.body.edges[edgeId].via.id; + if (viaId) { + this.body.edges[edgeId].via = undefined; + delete this.body.nodes[viaId]; + } + // this removes the edge from node.edges, which is why edgeIds is formed + this.body.edges[edgeId].disconnect(); + delete this.body.edges[edgeId]; + } - // force the ID to remain the same - clusterNodeProperties.id = clusterId; + // remove clusterNode + delete this.body.nodes[clusterNodeId]; + if (refreshData === true) { + this.body.emitter.emit("_dataChanged"); + } + } + }, { + key: "_connectEdge", - // create the clusterNode - var clusterNode = this.body.functions.createNode(clusterNodeProperties, Cluster); - clusterNode.isCluster = true; - clusterNode.containedNodes = childNodesObj; - clusterNode.containedEdges = childEdgesObj; + /** + * Connect an edge that was previously contained from cluster A to cluster B if the node that it was originally connected to + * is currently residing in cluster B + * @param edge + * @param nodeId + * @param from + * @private + */ + value: function _connectEdge(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(); + } + }, { + key: "_getClusterStack", + /** + * Get the stack clusterId's that a certain node resides in. cluster A -> cluster B -> cluster C -> node + * @param nodeId + * @returns {Array} + * @private + */ + value: function _getClusterStack(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.body.nodes[nodeId]); + return stack; + } + }, { + key: "_getConnectedId", - // disable the childEdges - for (var edgeId in childEdgesObj) { - if (childEdgesObj.hasOwnProperty(edgeId)) { - if (this.body.edges[edgeId] !== undefined) { - var edge = this.body.edges[edgeId]; - edge.togglePhysics(false); - edge.options.hidden = true; - } - } - } + /** + * Get the Id the node is connected to + * @param edge + * @param nodeId + * @returns {*} + * @private + */ + value: function _getConnectedId(edge, nodeId) { + if (edge.toId != nodeId) { + return edge.toId; + } else if (edge.fromId != nodeId) { + return edge.fromId; + } else { + return edge.fromId; + } + } + }, { + key: "_getHubSize", + /** + * 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 + */ + value: function _getHubSize() { + var average = 0; + var averageSquared = 0; + var hubCounter = 0; + var largestHub = 0; + + for (var i = 0; i < this.body.nodeIndices.length; i++) { + var node = this.body.nodes[this.body.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; - // disable the childNodes - for (var nodeId in childNodesObj) { - if (childNodesObj.hasOwnProperty(nodeId)) { - this.clusteredNodes[nodeId] = { clusterId: clusterNodeProperties.id, node: this.body.nodes[nodeId] }; - this.body.nodes[nodeId].togglePhysics(false); - this.body.nodes[nodeId].options.hidden = true; - } - } + var variance = averageSquared - Math.pow(average, 2); + var standardDeviation = Math.sqrt(variance); + var hubThreshold = Math.floor(average + 2 * standardDeviation); - // finally put the cluster node into global - this.body.nodes[clusterNodeProperties.id] = clusterNode; + // always have at least one to cluster + if (hubThreshold > largestHub) { + hubThreshold = largestHub; + } + return hubThreshold; + } + }]); - // push new edges to global - for (var i = 0; i < newEdges.length; i++) { - this.body.edges[newEdges[i].id] = newEdges[i]; - this.body.edges[newEdges[i].id].connect(); - } + return ClusterEngine; + })(); - // set ID to undefined so no duplicates arise - clusterNodeProperties.id = undefined; + exports["default"] = ClusterEngine; + module.exports = exports["default"]; +/***/ }, +/* 54 */ +/***/ function(module, exports, __webpack_require__) { - // wrap up - if (refreshData === true) { - this.body.emitter.emit("_dataChanged"); - } - }, - writable: true, - configurable: true - }, - isCluster: { + 'use strict'; + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; - /** - * Check if a node is a cluster. - * @param nodeId - * @returns {*} - */ - value: function isCluster(nodeId) { - if (this.body.nodes[nodeId] !== undefined) { - return this.body.nodes[nodeId].isCluster === true; - } else { - console.log("Node does not exist."); - return false; - } - }, - writable: true, - configurable: true - }, - _getClusterPosition: { + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); - /** - * 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 - */ - value: function _getClusterPosition(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) }; - }, - writable: true, - configurable: true - }, - openCluster: { + Object.defineProperty(exports, '__esModule', { + value: true + }); + if (typeof window !== 'undefined') { + window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; + } + var util = __webpack_require__(1); - /** - * Open a cluster by calling this function. - * @param {String} clusterNodeId | the ID of the cluster node - * @param {Boolean} refreshData | wrap up afterwards if not true - */ - value: function openCluster(clusterNodeId) { - var refreshData = arguments[1] === undefined ? true : arguments[1]; - // kill conditions - if (clusterNodeId === undefined) { - throw new Error("No clusterNodeId supplied to openCluster."); - } - if (this.body.nodes[clusterNodeId] === undefined) { - throw new Error("The clusterNodeId supplied to openCluster does not exist."); - } - if (this.body.nodes[clusterNodeId].containedNodes === undefined) { - console.log("The node:" + clusterNodeId + " is not a cluster.");return; - }; + var CanvasRenderer = (function () { + function CanvasRenderer(body, canvas) { + var _this = this; - var clusterNode = this.body.nodes[clusterNodeId]; - var containedNodes = clusterNode.containedNodes; - var containedEdges = clusterNode.containedEdges; + _classCallCheck(this, CanvasRenderer); - // release nodes - for (var nodeId in containedNodes) { - if (containedNodes.hasOwnProperty(nodeId)) { - var containedNode = this.body.nodes[nodeId]; - containedNode = containedNodes[nodeId]; - // inherit position - containedNode.x = clusterNode.x; - containedNode.y = clusterNode.y; + this.body = body; + this.canvas = canvas; - // inherit speed - containedNode.vx = clusterNode.vx; - containedNode.vy = clusterNode.vy; + this.redrawRequested = false; + this.renderTimer = false; + this.requiresTimeout = true; + this.renderingActive = false; + this.renderRequests = 0; + this.pixelRatio = undefined; + this.allowRedrawRequests = true; - containedNode.options.hidden = false; - containedNode.togglePhysics(true); + this.dragging = false; - delete this.clusteredNodes[nodeId]; - } - } + this.body.emitter.on('dragStart', function () { + _this.dragging = true; + }); + this.body.emitter.on('dragEnd', function () { + return _this.dragging = false; + }); + this.body.emitter.on('_redraw', function () { + if (_this.renderingActive === false) { + _this._redraw(); + } + }); + this.body.emitter.on('_blockRedrawRequests', function () { + _this.allowRedrawRequests = false; + }); + this.body.emitter.on('_allowRedrawRequests', function () { + _this.allowRedrawRequests = true; + }); + this.body.emitter.on('_requestRedraw', this._requestRedraw.bind(this)); + this.body.emitter.on('_startRendering', function () { + _this.renderRequests += 1; + _this.renderingActive = true; + _this._startRendering(); + }); + this.body.emitter.on('_stopRendering', function () { + _this.renderRequests -= 1; + _this.renderingActive = _this.renderRequests > 0; + }); - // release edges - for (var edgeId in containedEdges) { - if (containedEdges.hasOwnProperty(edgeId)) { - var edge = this.body.edges[edgeId]; - edge.options.hidden = false; - edge.togglePhysics(true); - } - } + this.options = {}; + this.defaultOptions = { + hideEdgesOnDrag: false, + hideNodesOnDrag: false + }; + util.extend(this.options, this.defaultOptions); + + this._determineBrowserMethod(); + } - // remove all temporary edges - for (var i = 0; i < clusterNode.edges.length; i++) { - var edgeId = clusterNode.edges[i].id; - var viaId = this.body.edges[edgeId].via.id; - if (viaId) { - this.body.edges[edgeId].via = undefined; - delete this.body.nodes[viaId]; + _createClass(CanvasRenderer, [{ + key: 'setOptions', + value: function setOptions(options) { + if (options !== undefined) { + util.deepExtend(this.options, options); + } + } + }, { + key: '_startRendering', + value: function _startRendering() { + if (this.renderingActive === true) { + if (!this.renderTimer) { + if (this.requiresTimeout === true) { + this.renderTimer = window.setTimeout(this._renderStep.bind(this), this.simulationInterval); // wait this.renderTimeStep milliseconds and perform the animation step function + } else { + this.renderTimer = window.requestAnimationFrame(this._renderStep.bind(this)); // wait this.renderTimeStep milliseconds and perform the animation step function } - // this removes the edge from node.edges, which is why edgeIds is formed - this.body.edges[edgeId].disconnect(); - delete this.body.edges[edgeId]; } + } else {} + } + }, { + key: '_renderStep', + value: function _renderStep() { + // reset the renderTimer so a new scheduled animation step can be set + this.renderTimer = undefined; - // remove clusterNode - delete this.body.nodes[clusterNodeId]; + if (this.requiresTimeout === true) { + // this schedules a new simulation step + this._startRendering(); + } - if (refreshData === true) { - this.body.emitter.emit("_dataChanged"); - } - }, - writable: true, - configurable: true - }, - _connectEdge: { + this._redraw(); + if (this.requiresTimeout === false) { + // this schedules a new simulation step + this._startRendering(); + } + } + }, { + key: 'redraw', + /** + * Redraw the network with the current data + * chart will be resized too. + */ + value: function redraw() { + this._redraw(); + } + }, { + key: '_requestRedraw', - /** - * Connect an edge that was previously contained from cluster A to cluster B if the node that it was originally connected to - * is currently residing in cluster B - * @param edge - * @param nodeId - * @param from - * @private - */ - value: function _connectEdge(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; + /** + * 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 + */ + value: function _requestRedraw() { + if (this.redrawRequested !== true && this.renderingActive === false && this.allowRedrawRequests === true) { + this.redrawRequested = true; + if (this.requiresTimeout === true) { + window.setTimeout(this._redraw.bind(this, false), 0); } else { - edge.to = clusterStack[clusterStack.length - 1]; - edge.toId = clusterStack[clusterStack.length - 1].id; - clusterStack.pop(); - edge.toArray = clusterStack; + window.requestAnimationFrame(this._redraw.bind(this, false)); } - edge.connect(); - }, - writable: true, - configurable: true - }, - _getClusterStack: { + } + } + }, { + key: '_redraw', + value: function _redraw() { + var hidden = arguments[0] === undefined ? false : arguments[0]; - /** - * Get the stack clusterId's that a certain node resides in. cluster A -> cluster B -> cluster C -> node - * @param nodeId - * @returns {Array} - * @private - */ - value: function _getClusterStack(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.body.nodes[nodeId]); - return stack; - }, - writable: true, - configurable: true - }, - _getConnectedId: { + this.body.emitter.emit('initRedraw'); + this.redrawRequested = false; + var ctx = this.canvas.frame.canvas.getContext('2d'); - /** - * Get the Id the node is connected to - * @param edge - * @param nodeId - * @returns {*} - * @private - */ - value: function _getConnectedId(edge, nodeId) { - if (edge.toId != nodeId) { - return edge.toId; - } else if (edge.fromId != nodeId) { - return edge.fromId; - } else { - return edge.fromId; + // when the container div was hidden, this fixes it back up! + if (this.canvas.frame.canvas.width === 0 || this.canvas.frame.canvas.height === 0) { + this.canvas.setSize(); + } + + if (this.pixelRation === undefined) { + this.pixelRatio = (window.devicePixelRatio || 1) / (ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1); + } + + ctx.setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0); + + // clear the canvas + var w = this.canvas.frame.canvas.clientWidth; + var h = this.canvas.frame.canvas.clientHeight; + ctx.clearRect(0, 0, w, h); + + this.body.emitter.emit('beforeDrawing', ctx); + + // set scaling and translation + ctx.save(); + ctx.translate(this.body.view.translation.x, this.body.view.translation.y); + ctx.scale(this.body.view.scale, this.body.view.scale); + + if (hidden === false) { + if (this.dragging === false || this.dragging === true && this.options.hideEdgesOnDrag === false) { + this._drawEdges(ctx); } - }, - writable: true, - configurable: true - }, - _getHubSize: { + } - /** - * 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 - */ - value: function _getHubSize() { - var average = 0; - var averageSquared = 0; - var hubCounter = 0; - var largestHub = 0; - - for (var i = 0; i < this.body.nodeIndices.length; i++) { - var node = this.body.nodes[this.body.nodeIndices[i]]; - if (node.edges.length > largestHub) { - largestHub = node.edges.length; + if (this.dragging === false || this.dragging === true && this.options.hideNodesOnDrag === false) { + this._drawNodes(ctx, hidden); + } + + if (this.controlNodesActive === true) { + this._drawControlNodes(ctx); + } + + //this.physics.nodesSolver._debug(ctx,"#F00F0F"); + + this.body.emitter.emit('afterDrawing', ctx); + + // restore original scaling and translation + ctx.restore(); + + if (hidden === true) { + ctx.clearRect(0, 0, w, h); + } + } + }, { + key: '_drawNodes', + + /** + * Redraw all nodes + * The 2d context of a HTML canvas can be retrieved by canvas.getContext('2d'); + * @param {CanvasRenderingContext2D} ctx + * @param {Boolean} [alwaysShow] + * @private + */ + value: function _drawNodes(ctx) { + var alwaysShow = arguments[1] === undefined ? false : arguments[1]; + + var nodes = this.body.nodes; + var nodeIndices = this.body.nodeIndices; + var node; + var selected = []; + + // draw unselected nodes; + for (var i = 0; i < nodeIndices.length; i++) { + node = nodes[nodeIndices[i]]; + // set selected nodes aside + if (node.isSelected()) { + selected.push(nodeIndices[i]); + } else { + if (alwaysShow === true) { + node.draw(ctx); } - average += node.edges.length; - averageSquared += Math.pow(node.edges.length, 2); - hubCounter += 1; + // todo: replace check + //else if (node.inArea() === true) { + node.draw(ctx); + //} } - average = average / hubCounter; - averageSquared = averageSquared / hubCounter; + } - var variance = averageSquared - Math.pow(average, 2); - var standardDeviation = Math.sqrt(variance); + // draw the selected nodes on top + for (var i = 0; i < selected.length; i++) { + node = nodes[selected[i]]; + node.draw(ctx); + } + } + }, { + key: '_drawEdges', - var hubThreshold = Math.floor(average + 2 * standardDeviation); + /** + * Redraw all edges + * The 2d context of a HTML canvas can be retrieved by canvas.getContext('2d'); + * @param {CanvasRenderingContext2D} ctx + * @private + */ + value: function _drawEdges(ctx) { + var edges = this.body.edges; + var edgeIndices = this.body.edgeIndices; + var edge; - // always have at least one to cluster - if (hubThreshold > largestHub) { - hubThreshold = largestHub; + for (var i = 0; i < edgeIndices.length; i++) { + edge = edges[edgeIndices[i]]; + if (edge.connected === true) { + edge.draw(ctx); } + } + } + }, { + key: '_drawControlNodes', - return hubThreshold; - }, - writable: true, - configurable: true + /** + * Redraw all edges + * The 2d context of a HTML canvas can be retrieved by canvas.getContext('2d'); + * @param {CanvasRenderingContext2D} ctx + * @private + */ + value: function _drawControlNodes(ctx) { + var edges = this.body.edges; + var edgeIndices = this.body.edgeIndices; + var edge; + + for (var i = 0; i < edgeIndices.length; i++) { + edge = edges[edgeIndices[i]]; + edge._drawControlNodes(ctx); + } } - }); + }, { + key: '_determineBrowserMethod', - return ClusterEngine; + /** + * Determine if the browser requires a setTimeout or a requestAnimationFrame. This was required because + * some implementations (safari and IE9) did not support requestAnimationFrame + * @private + */ + value: function _determineBrowserMethod() { + if (typeof window !== 'undefined') { + 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; + } + } + } else { + this.requiresTimeout = true; + } + } + }]); + + return CanvasRenderer; })(); - module.exports = ClusterEngine; + exports['default'] = CanvasRenderer; + module.exports = exports['default']; /***/ }, -/* 55 */, -/* 56 */ +/* 55 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + Object.defineProperty(exports, '__esModule', { + value: true + }); var Hammer = __webpack_require__(41); - var hammerUtil = __webpack_require__(64); + var hammerUtil = __webpack_require__(44); var util = __webpack_require__(1); @@ -20402,9 +20863,11 @@ return /******/ (function(modules) { // webpackBootstrap * nodes. * @private */ + var Canvas = (function () { function Canvas(body) { var _this = this; + _classCallCheck(this, Canvas); this.body = body; @@ -20412,13 +20875,13 @@ return /******/ (function(modules) { // webpackBootstrap this.options = {}; this.defaultOptions = { - width: "100%", - height: "100%" + width: '100%', + height: '100%' }; util.extend(this.options, this.defaultOptions); // bind the events - this.body.emitter.once("resize", function (obj) { + this.body.emitter.once('resize', function (obj) { if (obj.width !== 0) { _this.body.view.translation.x = obj.width * 0.5; } @@ -20426,303 +20889,306 @@ return /******/ (function(modules) { // webpackBootstrap _this.body.view.translation.y = obj.height * 0.5; } }); - this.body.emitter.on("destroy", function () { + this.body.emitter.on('destroy', function () { return _this.hammer.destroy(); }); // automatically adapt to a changing size of the browser. window.onresize = function () { - _this.setSize();_this.body.emitter.emit("_redraw"); + _this.setSize();_this.body.emitter.emit('_redraw'); }; } - _prototypeProperties(Canvas, null, { - setOptions: { - value: function setOptions(options) { - if (options !== undefined) { - util.deepExtend(this.options, options); + _createClass(Canvas, [{ + key: 'setOptions', + value: function setOptions(options) { + if (options !== undefined) { + if (options.width !== undefined) { + this.options.width = this._prepareValue(options.width); } - }, - writable: true, - configurable: true - }, - create: { - - - /** - * Create the HTML - */ - value: function create() { - // remove all elements from the container element. - while (this.body.container.hasChildNodes()) { - this.body.container.removeChild(this.body.container.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; // tab index is required for keycharm to bind keystrokes to the div instead of the window - - ////////////////////////////////////////////////////////////////// - - 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.frame.canvas.getContext("2d").setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0); + if (options.height !== undefined) { + this.options.height = this._prepareValue(options.height); + } + } + } + }, { + key: '_prepareValue', + value: function _prepareValue(value) { + if (typeof value === 'number') { + return value + 'px'; + } else if (typeof value === 'string') { + if (value.indexOf('%') !== -1 || value.indexOf('px') !== -1) { + return value; + } else if (value.indexOf('%') === -1) { + return value + 'px'; } + } + throw new Error('Could not use the value supplie for width or height:' + value); + } + }, { + key: '_create', - // add the frame to the container element - this.body.container.appendChild(this.frame); + /** + * Create the HTML + */ + value: function _create() { + // remove all elements from the container element. + while (this.body.container.hasChildNodes()) { + this.body.container.removeChild(this.body.container.firstChild); + } - this.body.view.scale = 1; - this.body.view.translation = { x: 0.5 * this.frame.canvas.clientWidth, y: 0.5 * this.frame.canvas.clientHeight }; + 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; // tab index is required for keycharm to bind keystrokes to the div instead of the window + + ////////////////////////////////////////////////////////////////// + + 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._bindHammer(); - }, - writable: true, - configurable: true - }, - _bindHammer: { + this.frame.canvas.getContext('2d').setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0); + } + // add the frame to the container element + this.body.container.appendChild(this.frame); - /** - * This function binds hammer, it can be repeated over and over due to the uniqueness check. - * @private - */ - value: function _bindHammer() { - var _this = this; - if (this.hammer !== undefined) { - this.hammer.destroy(); - } - this.drag = {}; - this.pinch = {}; + this.body.view.scale = 1; + this.body.view.translation = { x: 0.5 * this.frame.canvas.clientWidth, y: 0.5 * this.frame.canvas.clientHeight }; - // init hammer - this.hammer = new Hammer(this.frame.canvas); - this.hammer.get("pinch").set({ enable: true }); + this._bindHammer(); + } + }, { + key: '_bindHammer', - hammerUtil.onTouch(this.hammer, function (event) { - _this.body.eventListeners.onTouch(event); - }); - this.hammer.on("tap", function (event) { - _this.body.eventListeners.onTap(event); - }); - this.hammer.on("doubletap", function (event) { - _this.body.eventListeners.onDoubleTap(event); - }); - this.hammer.on("press", function (event) { - _this.body.eventListeners.onHold(event); - }); - this.hammer.on("panstart", function (event) { - _this.body.eventListeners.onDragStart(event); - }); - this.hammer.on("panmove", function (event) { - _this.body.eventListeners.onDrag(event); - }); - this.hammer.on("panend", function (event) { - _this.body.eventListeners.onDragEnd(event); - }); - this.hammer.on("pinch", function (event) { - _this.body.eventListeners.onPinch(event); - }); + /** + * This function binds hammer, it can be repeated over and over due to the uniqueness check. + * @private + */ + value: function _bindHammer() { + var _this2 = this; - // TODO: neatly cleanup these handlers when re-creating the Canvas, IF these are done with hammer, event.stopPropagation will not work? - this.frame.canvas.addEventListener("mousewheel", function (event) { - _this.body.eventListeners.onMouseWheel(event); - }); - this.frame.canvas.addEventListener("DOMMouseScroll", function (event) { - _this.body.eventListeners.onMouseWheel(event); - }); + if (this.hammer !== undefined) { + this.hammer.destroy(); + } + this.drag = {}; + this.pinch = {}; - this.frame.canvas.addEventListener("mousemove", function (event) { - _this.body.eventListeners.onMouseMove(event); - }); + // init hammer + this.hammer = new Hammer(this.frame.canvas); + this.hammer.get('pinch').set({ enable: true }); - this.hammerFrame = new Hammer(this.frame); - hammerUtil.onRelease(this.hammerFrame, function (event) { - _this.body.eventListeners.onRelease(event); - }); - }, - writable: true, - configurable: true - }, - setSize: { + hammerUtil.onTouch(this.hammer, function (event) { + _this2.body.eventListeners.onTouch(event); + }); + this.hammer.on('tap', function (event) { + _this2.body.eventListeners.onTap(event); + }); + this.hammer.on('doubletap', function (event) { + _this2.body.eventListeners.onDoubleTap(event); + }); + this.hammer.on('press', function (event) { + _this2.body.eventListeners.onHold(event); + }); + this.hammer.on('panstart', function (event) { + _this2.body.eventListeners.onDragStart(event); + }); + this.hammer.on('panmove', function (event) { + _this2.body.eventListeners.onDrag(event); + }); + this.hammer.on('panend', function (event) { + _this2.body.eventListeners.onDragEnd(event); + }); + this.hammer.on('pinch', function (event) { + _this2.body.eventListeners.onPinch(event); + }); + // TODO: neatly cleanup these handlers when re-creating the Canvas, IF these are done with hammer, event.stopPropagation will not work? + this.frame.canvas.addEventListener('mousewheel', function (event) { + _this2.body.eventListeners.onMouseWheel(event); + }); + this.frame.canvas.addEventListener('DOMMouseScroll', function (event) { + _this2.body.eventListeners.onMouseWheel(event); + }); - /** - * 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%') - */ - value: function setSize() { - var width = arguments[0] === undefined ? this.options.width : arguments[0]; - var height = arguments[1] === undefined ? this.options.height : arguments[1]; - var emitEvent = false; - var oldWidth = this.frame.canvas.width; - var oldHeight = this.frame.canvas.height; + this.frame.canvas.addEventListener('mousemove', function (event) { + _this2.body.eventListeners.onMouseMove(event); + }); - if (width != this.options.width || height != this.options.height || this.frame.style.width != width || this.frame.style.height != height) { - this.frame.style.width = width; - this.frame.style.height = height; + this.hammerFrame = new Hammer(this.frame); + hammerUtil.onRelease(this.hammerFrame, function (event) { + _this2.body.eventListeners.onRelease(event); + }); + } + }, { + key: 'setSize', - this.frame.canvas.style.width = "100%"; - this.frame.canvas.style.height = "100%"; + /** + * 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%') + */ + value: function setSize() { + var width = arguments[0] === undefined ? this.options.width : arguments[0]; + var height = arguments[1] === undefined ? this.options.height : arguments[1]; - this.frame.canvas.width = this.frame.canvas.clientWidth * this.pixelRatio; - this.frame.canvas.height = this.frame.canvas.clientHeight * this.pixelRatio; + width = this._prepareValue(width); + height = this._prepareValue(height); - this.options.width = width; - this.options.height = height; + var emitEvent = false; + var oldWidth = this.frame.canvas.width; + var oldHeight = this.frame.canvas.height; - emitEvent = true; - } else { - // this would adapt the width of the canvas to the width from 100% if and only if - // there is a change. + if (width != this.options.width || height != this.options.height || this.frame.style.width != width || this.frame.style.height != height) { + this.frame.style.width = width; + this.frame.style.height = height; - 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; - } - } + this.frame.canvas.style.width = '100%'; + this.frame.canvas.style.height = '100%'; - if (emitEvent === true) { - this.body.emitter.emit("resize", { width: this.frame.canvas.width / this.pixelRatio, height: this.frame.canvas.height / this.pixelRatio, oldWidth: oldWidth / this.pixelRatio, oldHeight: oldHeight / this.pixelRatio }); - } - }, - writable: true, - configurable: true - }, - _XconvertDOMtoCanvas: { + this.frame.canvas.width = this.frame.canvas.clientWidth * this.pixelRatio; + this.frame.canvas.height = this.frame.canvas.clientHeight * this.pixelRatio; + this.options.width = width; + this.options.height = height; - /** - * 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 - */ - value: function _XconvertDOMtoCanvas(x) { - return (x - this.body.view.translation.x) / this.body.view.scale; - }, - writable: true, - configurable: true - }, - _XconvertCanvasToDOM: { + emitEvent = true; + } else { + // this would adapt the width of the canvas to the width from 100% if and only if + // there is a change. - /** - * 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 - */ - value: function _XconvertCanvasToDOM(x) { - return x * this.body.view.scale + this.body.view.translation.x; - }, - writable: true, - configurable: true - }, - _YconvertDOMtoCanvas: { + 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; + } + } - /** - * 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 - */ - value: function _YconvertDOMtoCanvas(y) { - return (y - this.body.view.translation.y) / this.body.view.scale; - }, - writable: true, - configurable: true - }, - _YconvertCanvasToDOM: { + if (emitEvent === true) { + this.body.emitter.emit('resize', { width: this.frame.canvas.width / this.pixelRatio, height: this.frame.canvas.height / this.pixelRatio, oldWidth: oldWidth / this.pixelRatio, oldHeight: oldHeight / this.pixelRatio }); + } + } + }, { + key: '_XconvertDOMtoCanvas', - /** - * 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 - */ - value: function _YconvertCanvasToDOM(y) { - return y * this.body.view.scale + this.body.view.translation.y; - }, - writable: true, - configurable: true - }, - canvasToDOM: { + /** + * 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 + */ + value: function _XconvertDOMtoCanvas(x) { + return (x - this.body.view.translation.x) / this.body.view.scale; + } + }, { + key: '_XconvertCanvasToDOM', + + /** + * Convert the X coordinate in canvas-space (the simulation sandbox, which the camera looks upon) to + * the X coordinate in DOM-space (coordinate point in browser relative to the container div) + * @param {number} x + * @returns {number} + * @private + */ + value: function _XconvertCanvasToDOM(x) { + return x * this.body.view.scale + this.body.view.translation.x; + } + }, { + key: '_YconvertDOMtoCanvas', + /** + * Convert the Y coordinate in DOM-space (coordinate point in browser relative to the container div) to + * the Y coordinate in canvas-space (the simulation sandbox, which the camera looks upon) + * @param {number} y + * @returns {number} + * @private + */ + value: function _YconvertDOMtoCanvas(y) { + return (y - this.body.view.translation.y) / this.body.view.scale; + } + }, { + key: '_YconvertCanvasToDOM', - /** - * - * @param {object} pos = {x: number, y: number} - * @returns {{x: number, y: number}} - * @constructor - */ - value: function canvasToDOM(pos) { - return { x: this._XconvertCanvasToDOM(pos.x), y: this._YconvertCanvasToDOM(pos.y) }; - }, - writable: true, - configurable: true - }, - DOMtoCanvas: { + /** + * 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 + */ + value: function _YconvertCanvasToDOM(y) { + return y * this.body.view.scale + this.body.view.translation.y; + } + }, { + key: 'canvasToDOM', - /** - * - * @param {object} pos = {x: number, y: number} - * @returns {{x: number, y: number}} - * @constructor - */ - value: function DOMtoCanvas(pos) { - return { x: this._XconvertDOMtoCanvas(pos.x), y: this._YconvertDOMtoCanvas(pos.y) }; - }, - writable: true, - configurable: true + /** + * + * @param {object} pos = {x: number, y: number} + * @returns {{x: number, y: number}} + * @constructor + */ + value: function canvasToDOM(pos) { + return { x: this._XconvertCanvasToDOM(pos.x), y: this._YconvertCanvasToDOM(pos.y) }; } - }); + }, { + key: 'DOMtoCanvas', + + /** + * + * @param {object} pos = {x: number, y: number} + * @returns {{x: number, y: number}} + * @constructor + */ + value: function DOMtoCanvas(pos) { + return { x: this._XconvertDOMtoCanvas(pos.x), y: this._YconvertDOMtoCanvas(pos.y) }; + } + }]); return Canvas; })(); - module.exports = Canvas; + exports['default'] = Canvas; + module.exports = exports['default']; /***/ }, -/* 57 */ +/* 56 */ /***/ function(module, exports, __webpack_require__) { "use strict"; - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + Object.defineProperty(exports, "__esModule", { + value: true + }); var util = __webpack_require__(1); var View = (function () { function View(body, canvas) { var _this = this; + _classCallCheck(this, View); this.body = body; @@ -20748,33 +21214,49 @@ return /******/ (function(modules) { // webpackBootstrap this.body.emitter.on("unlockNode", this.releaseNode.bind(this)); } - _prototypeProperties(View, null, { - setOptions: { - value: function setOptions() { - var options = arguments[0] === undefined ? {} : arguments[0]; - this.options = options; - }, - writable: true, - configurable: true - }, - _getRange: { + _createClass(View, [{ + key: "setOptions", + value: function setOptions() { + var options = arguments[0] === undefined ? {} : arguments[0]; + this.options = options; + } + }, { + key: "_getRange", - // zoomExtent - /** - * Find the center position of the network - * @private - */ - value: function _getRange() { - var specificNodes = arguments[0] === undefined ? [] : arguments[0]; - var minY = 1000000000, - maxY = -1000000000, - minX = 1000000000, - maxX = -1000000000, - node; - if (specificNodes.length > 0) { - for (var i = 0; i < specificNodes.length; i++) { - node = this.body.nodes[specificNodes[i]]; + // zoomExtent + /** + * Find the center position of the network + * @private + */ + value: function _getRange() { + var specificNodes = arguments[0] === undefined ? [] : arguments[0]; + + var minY = 1000000000, + maxY = -1000000000, + minX = 1000000000, + maxX = -1000000000, + node; + if (specificNodes.length > 0) { + for (var i = 0; i < specificNodes.length; i++) { + node = this.body.nodes[specificNodes[i]]; + if (minX > node.shape.boundingBox.left) { + minX = node.shape.boundingBox.left; + } + if (maxX < node.shape.boundingBox.right) { + maxX = node.shape.boundingBox.right; + } + if (minY > node.shape.boundingBox.bottom) { + minY = node.shape.boundingBox.top; + } // top is negative, bottom is positive + if (maxY < node.shape.boundingBox.top) { + maxY = node.shape.boundingBox.bottom; + } // top is negative, bottom is positive + } + } else { + for (var nodeId in this.body.nodes) { + if (this.body.nodes.hasOwnProperty(nodeId)) { + node = this.body.nodes[nodeId]; if (minX > node.shape.boundingBox.left) { minX = node.shape.boundingBox.left; } @@ -20788,351 +21270,324 @@ return /******/ (function(modules) { // webpackBootstrap maxY = node.shape.boundingBox.bottom; } // top is negative, bottom is positive } - } else { - for (var nodeId in this.body.nodes) { - if (this.body.nodes.hasOwnProperty(nodeId)) { - node = this.body.nodes[nodeId]; - if (minX > node.shape.boundingBox.left) { - minX = node.shape.boundingBox.left; - } - if (maxX < node.shape.boundingBox.right) { - maxX = node.shape.boundingBox.right; - } - if (minY > node.shape.boundingBox.bottom) { - minY = node.shape.boundingBox.top; - } // top is negative, bottom is positive - if (maxY < node.shape.boundingBox.top) { - maxY = node.shape.boundingBox.bottom; - } // top is negative, bottom is positive - } - } } + } - if (minX === 1000000000 && maxX === -1000000000 && minY === 1000000000 && maxY === -1000000000) { - minY = 0, maxY = 0, minX = 0, maxX = 0; - } - return { minX: minX, maxX: maxX, minY: minY, maxY: maxY }; - }, - writable: true, - configurable: true - }, - _findCenter: { + if (minX === 1000000000 && maxX === -1000000000 && minY === 1000000000 && maxY === -1000000000) { + minY = 0, maxY = 0, minX = 0, maxX = 0; + } + return { minX: minX, maxX: maxX, minY: minY, maxY: maxY }; + } + }, { + key: "_findCenter", + /** + * @param {object} range = {minX: minX, maxX: maxX, minY: minY, maxY: maxY}; + * @returns {{x: number, y: number}} + * @private + */ + value: function _findCenter(range) { + return { x: 0.5 * (range.maxX + range.minX), + y: 0.5 * (range.maxY + range.minY) }; + } + }, { + key: "zoomExtent", - /** - * @param {object} range = {minX: minX, maxX: maxX, minY: minY, maxY: maxY}; - * @returns {{x: number, y: number}} - * @private - */ - value: function _findCenter(range) { - return { x: 0.5 * (range.maxX + range.minX), - y: 0.5 * (range.maxY + range.minY) }; - }, - writable: true, - configurable: true - }, - zoomExtent: { + /** + * This function zooms out to fit all data on screen based on amount of nodes + * @param {Object} + * @param {Boolean} [initialZoom] | zoom based on fitted formula or range, true = fitted, default = false; + * @param {Boolean} [disableStart] | If true, start is not called. + */ + value: function zoomExtent() { + var options = arguments[0] === undefined ? { nodes: [] } : arguments[0]; + var initialZoom = arguments[1] === undefined ? false : arguments[1]; + var range; + var zoomLevel; - /** - * This function zooms out to fit all data on screen based on amount of nodes - * @param {Object} - * @param {Boolean} [initialZoom] | zoom based on fitted formula or range, true = fitted, default = false; - * @param {Boolean} [disableStart] | If true, start is not called. - */ - value: function zoomExtent() { - var options = arguments[0] === undefined ? { nodes: [] } : arguments[0]; - var initialZoom = arguments[1] === undefined ? false : arguments[1]; - var range; - var zoomLevel; - - if (initialZoom === true) { - // check if more than half of the nodes have a predefined position. If so, we use the range, not the approximation. - var positionDefined = 0; - for (var nodeId in this.body.nodes) { - if (this.body.nodes.hasOwnProperty(nodeId)) { - var node = this.body.nodes[nodeId]; - if (node.predefinedPosition === true) { - positionDefined += 1; - } + if (initialZoom === true) { + // check if more than half of the nodes have a predefined position. If so, we use the range, not the approximation. + var positionDefined = 0; + for (var nodeId in this.body.nodes) { + if (this.body.nodes.hasOwnProperty(nodeId)) { + var node = this.body.nodes[nodeId]; + if (node.predefinedPosition === true) { + positionDefined += 1; } } - if (positionDefined > 0.5 * this.body.nodeIndices.length) { - this.zoomExtent(options, false); - return; - } - - range = this._getRange(options.nodes); + } + if (positionDefined > 0.5 * this.body.nodeIndices.length) { + this.zoomExtent(options, false); + return; + } - var numberOfNodes = this.body.nodeIndices.length; - zoomLevel = 12.662 / (numberOfNodes + 7.4147) + 0.0964822; // this is obtained from fitting a dataset from 5 points with scale levels that looked good. + range = this._getRange(options.nodes); - // correct for larger canvasses. - var factor = Math.min(this.canvas.frame.canvas.clientWidth / 600, this.canvas.frame.canvas.clientHeight / 600); - zoomLevel *= factor; - } else { - this.body.emitter.emit("_redraw", true); - 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; + var numberOfNodes = this.body.nodeIndices.length; + zoomLevel = 12.662 / (numberOfNodes + 7.4147) + 0.0964822; // this is obtained from fitting a dataset from 5 points with scale levels that looked good. - var xZoomLevel = this.canvas.frame.canvas.clientWidth / xDistance; - var yZoomLevel = this.canvas.frame.canvas.clientHeight / yDistance; + // correct for larger canvasses. + var factor = Math.min(this.canvas.frame.canvas.clientWidth / 600, this.canvas.frame.canvas.clientHeight / 600); + zoomLevel *= factor; + } else { + this.body.emitter.emit("_redraw", true); + 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; - zoomLevel = xZoomLevel <= yZoomLevel ? xZoomLevel : yZoomLevel; - } + var xZoomLevel = this.canvas.frame.canvas.clientWidth / xDistance; + var yZoomLevel = this.canvas.frame.canvas.clientHeight / yDistance; - if (zoomLevel > 1) { - zoomLevel = 1; - } else if (zoomLevel === 0) { - zoomLevel = 1; - } + zoomLevel = xZoomLevel <= yZoomLevel ? xZoomLevel : yZoomLevel; + } - var center = this._findCenter(range); - var animationOptions = { position: center, scale: zoomLevel, animation: options }; - this.moveTo(animationOptions); - }, - writable: true, - configurable: true - }, - focusOnNode: { + if (zoomLevel > 1) { + zoomLevel = 1; + } else if (zoomLevel === 0) { + zoomLevel = 1; + } - // animation + var center = this._findCenter(range); + var animationOptions = { position: center, scale: zoomLevel, animation: options }; + this.moveTo(animationOptions); + } + }, { + key: "focusOnNode", - /** - * Center a node in view. - * - * @param {Number} nodeId - * @param {Number} [options] - */ - value: function focusOnNode(nodeId) { - var options = arguments[1] === undefined ? {} : arguments[1]; - if (this.body.nodes[nodeId] !== undefined) { - var nodePosition = { x: this.body.nodes[nodeId].x, y: this.body.nodes[nodeId].y }; - options.position = nodePosition; - options.lockedOnNode = nodeId; - - this.moveTo(options); - } else { - console.log("Node: " + nodeId + " cannot be found."); - } - }, - writable: true, - configurable: true - }, - moveTo: { + // animation - /** - * - * @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 - */ - value: function moveTo(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.body.view.scale; - } - if (options.position === undefined) { - options.position = this.body.view.translation; - } - 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 + /** + * Center a node in view. + * + * @param {Number} nodeId + * @param {Number} [options] + */ + value: function focusOnNode(nodeId) { + var options = arguments[1] === undefined ? {} : arguments[1]; - this.animateView(options); - }, - writable: true, - configurable: true - }, - animateView: { + if (this.body.nodes[nodeId] !== undefined) { + var nodePosition = { x: this.body.nodes[nodeId].x, y: this.body.nodes[nodeId].y }; + options.position = nodePosition; + options.lockedOnNode = nodeId; - /** - * - * @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 - */ - value: function animateView(options) { - if (options === undefined) { - return; - } - this.animationEasingFunction = options.animation.easingFunction; - // release if something focussed on the node - this.releaseNode(); - if (options.locked === true) { - this.lockedOnNodeId = options.lockedOnNode; - this.lockedOnNodeOffset = options.offset; - } + this.moveTo(options); + } else { + console.log("Node: " + nodeId + " cannot be found."); + } + } + }, { + key: "moveTo", - // forcefully complete the old animation if it was still running - if (this.easingTime != 0) { - this._transitionRedraw(true); // by setting easingtime to 1, we finish the animation. - } + /** + * + * @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 + */ + value: function moveTo(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.body.view.scale; + } + if (options.position === undefined) { + options.position = this.body.view.translation; + } + 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 - this.sourceScale = this.body.view.scale; - this.sourceTranslation = this.body.view.translation; - this.targetScale = options.scale; + this.animateView(options); + } + }, { + key: "animateView", - // set the scale so the viewCenter is based on the correct zoom level. This is overridden in the transitionRedraw - // but at least then we'll have the target transition - this.body.view.scale = this.targetScale; - var viewCenter = this.canvas.DOMtoCanvas({ x: 0.5 * this.canvas.frame.canvas.clientWidth, y: 0.5 * this.canvas.frame.canvas.clientHeight }); - 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 - }; + /** + * + * @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 + */ + value: function animateView(options) { + if (options === undefined) { + return; + } + this.animationEasingFunction = options.animation.easingFunction; + // release if something focussed on the node + this.releaseNode(); + if (options.locked === true) { + this.lockedOnNodeId = options.lockedOnNode; + this.lockedOnNodeOffset = options.offset; + } - // if the time is set to 0, don't do an animation - if (options.animation.duration === 0) { - if (this.lockedOnNodeId != undefined) { - this.viewFunction = this._lockedRedraw.bind(this); - this.body.emitter.on("initRedraw", this.viewFunction); - } else { - this.body.view.scale = this.targetScale; - this.body.view.translation = this.targetTranslation; - this.body.emitter.emit("_requestRedraw"); - } - } else { - this.animationSpeed = 1 / (60 * options.animation.duration * 0.001) || 1 / 60; // 60 for 60 seconds, 0.001 for milli's - this.animationEasingFunction = options.animation.easingFunction; + // forcefully complete the old animation if it was still running + if (this.easingTime != 0) { + this._transitionRedraw(true); // by setting easingtime to 1, we finish the animation. + } + this.sourceScale = this.body.view.scale; + this.sourceTranslation = this.body.view.translation; + 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.body.view.scale = this.targetScale; + var viewCenter = this.canvas.DOMtoCanvas({ x: 0.5 * this.canvas.frame.canvas.clientWidth, y: 0.5 * this.canvas.frame.canvas.clientHeight }); + 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 + }; - this.viewFunction = this._transitionRedraw.bind(this); + // if the time is set to 0, don't do an animation + if (options.animation.duration === 0) { + if (this.lockedOnNodeId != undefined) { + this.viewFunction = this._lockedRedraw.bind(this); this.body.emitter.on("initRedraw", this.viewFunction); - this.body.emitter.emit("_startRendering"); + } else { + this.body.view.scale = this.targetScale; + this.body.view.translation = this.targetTranslation; + this.body.emitter.emit("_requestRedraw"); } - }, - writable: true, - configurable: true - }, - _lockedRedraw: { + } else { + this.animationSpeed = 1 / (60 * options.animation.duration * 0.001) || 1 / 60; // 60 for 60 seconds, 0.001 for milli's + this.animationEasingFunction = options.animation.easingFunction; - /** - * used to animate smoothly by hijacking the redraw function. - * @private - */ - value: function _lockedRedraw() { - var nodePosition = { x: this.body.nodes[this.lockedOnNodeId].x, y: this.body.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.body.view.translation; - var targetTranslation = { - x: sourceTranslation.x + distanceFromCenter.x * this.body.view.scale + this.lockedOnNodeOffset.x, - y: sourceTranslation.y + distanceFromCenter.y * this.body.view.scale + this.lockedOnNodeOffset.y - }; + this.viewFunction = this._transitionRedraw.bind(this); + this.body.emitter.on("initRedraw", this.viewFunction); + this.body.emitter.emit("_startRendering"); + } + } + }, { + key: "_lockedRedraw", - this.body.view.translation = targetTranslation; - }, - writable: true, - configurable: true - }, - releaseNode: { - value: function releaseNode() { - if (this.lockedOnNodeId !== undefined && this.viewFunction !== undefined) { - this.body.emitter.off("initRedraw", this.viewFunction); - this.lockedOnNodeId = undefined; - this.lockedOnNodeOffset = undefined; - } - }, - writable: true, - configurable: true - }, - _transitionRedraw: { + /** + * used to animate smoothly by hijacking the redraw function. + * @private + */ + value: function _lockedRedraw() { + var nodePosition = { x: this.body.nodes[this.lockedOnNodeId].x, y: this.body.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.body.view.translation; + var targetTranslation = { + x: sourceTranslation.x + distanceFromCenter.x * this.body.view.scale + this.lockedOnNodeOffset.x, + y: sourceTranslation.y + distanceFromCenter.y * this.body.view.scale + this.lockedOnNodeOffset.y + }; - /** - * - * @param easingTime - * @private - */ - value: function _transitionRedraw() { - var finished = arguments[0] === undefined ? false : arguments[0]; - this.easingTime += this.animationSpeed; - this.easingTime = finished === true ? 1 : this.easingTime; + this.body.view.translation = targetTranslation; + } + }, { + key: "releaseNode", + value: function releaseNode() { + if (this.lockedOnNodeId !== undefined && this.viewFunction !== undefined) { + this.body.emitter.off("initRedraw", this.viewFunction); + this.lockedOnNodeId = undefined; + this.lockedOnNodeOffset = undefined; + } + } + }, { + key: "_transitionRedraw", - var progress = util.easingFunctions[this.animationEasingFunction](this.easingTime); + /** + * + * @param easingTime + * @private + */ + value: function _transitionRedraw() { + var finished = arguments[0] === undefined ? false : arguments[0]; - this.body.view.scale = this.sourceScale + (this.targetScale - this.sourceScale) * progress; - this.body.view.translation = { - x: this.sourceTranslation.x + (this.targetTranslation.x - this.sourceTranslation.x) * progress, - y: this.sourceTranslation.y + (this.targetTranslation.y - this.sourceTranslation.y) * progress - }; + this.easingTime += this.animationSpeed; + this.easingTime = finished === true ? 1 : this.easingTime; - // cleanup - if (this.easingTime >= 1) { - this.body.emitter.off("initRedraw", this.viewFunction); - this.easingTime = 0; - if (this.lockedOnNodeId != undefined) { - this.viewFunction = this._lockedRedraw.bind(this); - this.body.emitter.on("initRedraw", this.viewFunction); - } - this.body.emitter.emit("animationFinished"); + var progress = util.easingFunctions[this.animationEasingFunction](this.easingTime); + + this.body.view.scale = this.sourceScale + (this.targetScale - this.sourceScale) * progress; + this.body.view.translation = { + x: this.sourceTranslation.x + (this.targetTranslation.x - this.sourceTranslation.x) * progress, + y: this.sourceTranslation.y + (this.targetTranslation.y - this.sourceTranslation.y) * progress + }; + + // cleanup + if (this.easingTime >= 1) { + this.body.emitter.off("initRedraw", this.viewFunction); + this.easingTime = 0; + if (this.lockedOnNodeId != undefined) { + this.viewFunction = this._lockedRedraw.bind(this); + this.body.emitter.on("initRedraw", this.viewFunction); } - }, - writable: true, - configurable: true + this.body.emitter.emit("animationFinished"); + } } - }); + }]); return View; })(); - module.exports = View; + exports["default"] = View; + module.exports = exports["default"]; /***/ }, -/* 58 */ +/* 57 */ /***/ function(module, exports, __webpack_require__) { "use strict"; - var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; - - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { "default": obj }; }; var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; - var util = __webpack_require__(1); + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + Object.defineProperty(exports, "__esModule", { + value: true + }); + + var _NavigationHandler = __webpack_require__(77); + + var _NavigationHandler2 = _interopRequireWildcard(_NavigationHandler); + + var _Popup = __webpack_require__(78); - var NavigationHandler = _interopRequire(__webpack_require__(78)); + var _Popup2 = _interopRequireWildcard(_Popup); - var Popup = _interopRequire(__webpack_require__(79)); + var util = __webpack_require__(1); var InteractionHandler = (function () { function InteractionHandler(body, canvas, selectionHandler) { @@ -21141,7 +21596,7 @@ return /******/ (function(modules) { // webpackBootstrap this.body = body; this.canvas = canvas; this.selectionHandler = selectionHandler; - this.navigationHandler = new NavigationHandler(body, canvas); + this.navigationHandler = new _NavigationHandler2["default"](body, canvas); // bind the events from hammer to functions in this object this.body.eventListeners.onTap = this.onTap.bind(this); @@ -21192,661 +21647,618 @@ return /******/ (function(modules) { // webpackBootstrap util.extend(this.options, this.defaultOptions); } - _prototypeProperties(InteractionHandler, null, { - setOptions: { - value: function setOptions(options) { - if (options !== undefined) { - // extend all but the values in fields - var fields = ["keyboard", "tooltip"]; - util.selectiveNotDeepExtend(fields, this.options, options); + _createClass(InteractionHandler, [{ + key: "setOptions", + value: function setOptions(options) { + if (options !== undefined) { + // extend all but the values in fields + var fields = ["keyboard", "tooltip"]; + util.selectiveNotDeepExtend(fields, this.options, options); - // merge the keyboard options in. - util.mergeOptions(this.options, options, "keyboard"); + // merge the keyboard options in. + util.mergeOptions(this.options, options, "keyboard"); - if (options.tooltip) { - util.extend(this.options.tooltip, options.tooltip); - if (options.tooltip.color) { - this.options.tooltip.color = util.parseColor(options.tooltip.color); - } + if (options.tooltip) { + util.extend(this.options.tooltip, options.tooltip); + if (options.tooltip.color) { + this.options.tooltip.color = util.parseColor(options.tooltip.color); } } + } - this.navigationHandler.setOptions(this.options); - }, - writable: true, - configurable: true - }, - getPointer: { - + this.navigationHandler.setOptions(this.options); + } + }, { + key: "getPointer", - /** - * Get the pointer location from a touch location - * @param {{x: Number, y: Number}} touch - * @return {{x: Number, y: Number}} pointer - * @private - */ - value: function getPointer(touch) { - return { - x: touch.x - util.getAbsoluteLeft(this.canvas.frame.canvas), - y: touch.y - util.getAbsoluteTop(this.canvas.frame.canvas) - }; - }, - writable: true, - configurable: true - }, - onTouch: { + /** + * Get the pointer location from a touch location + * @param {{x: Number, y: Number}} touch + * @return {{x: Number, y: Number}} pointer + * @private + */ + value: function getPointer(touch) { + return { + x: touch.x - util.getAbsoluteLeft(this.canvas.frame.canvas), + y: touch.y - util.getAbsoluteTop(this.canvas.frame.canvas) + }; + } + }, { + key: "onTouch", + /** + * On start of a touch gesture, store the pointer + * @param event + * @private + */ + value: function onTouch(event) { + if (new Date().valueOf() - this.touchTime > 100) { + this.drag.pointer = this.getPointer(event.center); + this.drag.pinched = false; + this.pinch.scale = this.body.view.scale; + // to avoid double fireing of this event because we have two hammer instances. (on canvas and on frame) + this.touchTime = new Date().valueOf(); + } + } + }, { + key: "onTap", - /** - * On start of a touch gesture, store the pointer - * @param event - * @private - */ - value: function onTouch(event) { - if (new Date().valueOf() - this.touchTime > 100) { - this.drag.pointer = this.getPointer(event.center); - this.drag.pinched = false; - this.pinch.scale = this.body.view.scale; - // to avoid double fireing of this event because we have two hammer instances. (on canvas and on frame) - this.touchTime = new Date().valueOf(); - } - }, - writable: true, - configurable: true - }, - onTap: { + /** + * handle tap/click event: select/unselect a node + * @private + */ + value: function onTap(event) { + var pointer = this.getPointer(event.center); - /** - * handle tap/click event: select/unselect a node - * @private - */ - value: function onTap(event) { - var pointer = this.getPointer(event.center); + var previouslySelected = this.selectionHandler._getSelectedObjectCount() > 0; + var selected = this.selectionHandler.selectOnPoint(pointer); - var previouslySelected = this.selectionHandler._getSelectedObjectCount() > 0; - var selected = this.selectionHandler.selectOnPoint(pointer); + if (selected === true || previouslySelected === true && selected === false) { + // select or unselect + this.body.emitter.emit("select", this.selectionHandler.getSelection()); + } - if (selected === true || previouslySelected === true && selected === false) { - // select or unselect - this.body.emitter.emit("select", this.selectionHandler.getSelection()); - } + this.selectionHandler._generateClickEvent("click", pointer); + } + }, { + key: "onDoubleTap", - this.selectionHandler._generateClickEvent("click", pointer); - }, - writable: true, - configurable: true - }, - onDoubleTap: { + /** + * handle doubletap event + * @private + */ + value: function onDoubleTap(event) { + var pointer = this.getPointer(event.center); + this.selectionHandler._generateClickEvent("doubleClick", pointer); + } + }, { + key: "onHold", + /** + * handle long tap event: multi select nodes + * @private + */ + value: function onHold(event) { + var pointer = this.getPointer(event.center); - /** - * handle doubletap event - * @private - */ - value: function onDoubleTap(event) { - var pointer = this.getPointer(event.center); - this.selectionHandler._generateClickEvent("doubleClick", pointer); - }, - writable: true, - configurable: true - }, - onHold: { + var selectionChanged = this.selectionHandler.selectAdditionalOnPoint(pointer); + if (selectionChanged === true) { + // select or longpress + this.body.emitter.emit("select", this.selectionHandler.getSelection()); + } + this.selectionHandler._generateClickEvent("click", pointer); + } + }, { + key: "onRelease", - /** - * handle long tap event: multi select nodes - * @private - */ - value: function onHold(event) { - var pointer = this.getPointer(event.center); + /** + * handle the release of the screen + * + * @private + */ + value: function onRelease(event) { + this.body.emitter.emit("release", event); + } + }, { + key: "onDragStart", - var selectionChanged = this.selectionHandler.selectAdditionalOnPoint(pointer); + /** + * This function is called by onDragStart. + * It is separated out because we can then overload it for the datamanipulation system. + * + * @private + */ + value: function onDragStart(event) { + //in case the touch event was triggered on an external div, do the initial touch now. + if (this.drag.pointer === undefined) { + this.onTouch(event); + } - if (selectionChanged === true) { - // select or longpress - this.body.emitter.emit("select", this.selectionHandler.getSelection()); - } + // note: drag.pointer is set in onTouch to get the initial touch location + var node = this.selectionHandler.getNodeAt(this.drag.pointer); - this.selectionHandler._generateClickEvent("click", pointer); - }, - writable: true, - configurable: true - }, - onRelease: { + this.drag.dragging = true; + this.drag.selection = []; + this.drag.translation = util.extend({}, this.body.view.translation); // copy the object + this.drag.nodeId = undefined; + this.body.emitter.emit("dragStart", { nodeIds: this.selectionHandler.getSelection().nodes }); - /** - * handle the release of the screen - * - * @private - */ - value: function onRelease(event) { - this.body.emitter.emit("release", event); - }, - writable: true, - configurable: true - }, - onDragStart: { + if (node !== undefined && this.options.dragNodes === true) { + this.drag.nodeId = node.id; + // select the clicked node if not yet selected + if (node.isSelected() === false) { + this.selectionHandler.unselectAll(); + this.selectionHandler.selectObject(node); + } + + var selection = this.selectionHandler.selectionObj.nodes; + // create an array with the selected nodes and their original location and status + for (var nodeId in selection) { + if (selection.hasOwnProperty(nodeId)) { + var object = selection[nodeId]; + 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.options.fixed.x, + yFixed: object.options.fixed.y + }; + object.options.fixed.x = true; + object.options.fixed.y = true; - /** - * This function is called by onDragStart. - * It is separated out because we can then overload it for the datamanipulation system. - * - * @private - */ - value: function onDragStart(event) { - //in case the touch event was triggered on an external div, do the initial touch now. - if (this.drag.pointer === undefined) { - this.onTouch(event); + this.drag.selection.push(s); + } } + } + } + }, { + key: "onDrag", - // note: drag.pointer is set in onTouch to get the initial touch location - var node = this.selectionHandler.getNodeAt(this.drag.pointer); + /** + * handle drag event + * @private + */ + value: function onDrag(event) { + var _this = this; - this.drag.dragging = true; - this.drag.selection = []; - this.drag.translation = util.extend({}, this.body.view.translation); // copy the object - this.drag.nodeId = undefined; + if (this.drag.pinched === true) { + return; + } - this.body.emitter.emit("dragStart", { nodeIds: this.selectionHandler.getSelection().nodes }); + // remove the focus on node if it is focussed on by the focusOnNode + this.body.emitter.emit("unlockNode"); + + var pointer = this.getPointer(event.center); + var selection = this.drag.selection; + if (selection && selection.length && this.options.dragNodes === true) { + (function () { + // calculate delta's and new location + var deltaX = pointer.x - _this.drag.pointer.x; + var deltaY = pointer.y - _this.drag.pointer.y; + + // update position of all selected nodes + selection.forEach(function (selection) { + var node = selection.node; + // only move the node if it was not fixed initially + if (selection.xFixed === false) { + node.x = _this.canvas._XconvertDOMtoCanvas(_this.canvas._XconvertCanvasToDOM(selection.x) + deltaX); + } + // only move the node if it was not fixed initially + if (selection.yFixed === false) { + node.y = _this.canvas._YconvertDOMtoCanvas(_this.canvas._YconvertCanvasToDOM(selection.y) + deltaY); + } + }); - if (node !== undefined && this.options.dragNodes === true) { - this.drag.nodeId = node.id; - // select the clicked node if not yet selected - if (node.isSelected() === false) { - this.selectionHandler.unselectAll(); - this.selectionHandler.selectObject(node); + // start the simulation of the physics + _this.body.emitter.emit("startSimulation"); + })(); + } else { + // move the network + if (this.options.dragView === 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; - var selection = this.selectionHandler.selectionObj.nodes; - // create an array with the selected nodes and their original location and status - for (var nodeId in selection) { - if (selection.hasOwnProperty(nodeId)) { - var object = selection[nodeId]; - 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.options.fixed.x, - yFixed: object.options.fixed.y - }; - - object.options.fixed.x = true; - object.options.fixed.y = true; - - this.drag.selection.push(s); - } - } + this.body.view.translation = { x: this.drag.translation.x + diffX, y: this.drag.translation.y + diffY }; + this.body.emitter.emit("_redraw"); } - }, - writable: true, - configurable: true - }, - onDrag: { - + } + } + }, { + key: "onDragEnd", - /** - * handle drag event - * @private - */ - value: function onDrag(event) { - var _this = this; - if (this.drag.pinched === true) { - return; - } + /** + * handle drag start event + * @private + */ + value: function onDragEnd(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.options.fixed.x = s.xFixed; + s.node.options.fixed.y = s.yFixed; + }); + this.body.emitter.emit("startSimulation"); + } else { + this.body.emitter.emit("_requestRedraw"); + } - // remove the focus on node if it is focussed on by the focusOnNode - this.body.emitter.emit("unlockNode"); + this.body.emitter.emit("dragEnd", { nodeIds: this.selectionHandler.getSelection().nodes }); + } + }, { + key: "onPinch", - var pointer = this.getPointer(event.center); - var selection = this.drag.selection; - if (selection && selection.length && this.options.dragNodes === true) { - (function () { - // calculate delta's and new location - var deltaX = pointer.x - _this.drag.pointer.x; - var deltaY = pointer.y - _this.drag.pointer.y; + /** + * Handle pinch event + * @param event + * @private + */ + value: function onPinch(event) { + var pointer = this.getPointer(event.center); - // update position of all selected nodes - selection.forEach(function (selection) { - var node = selection.node; - // only move the node if it was not fixed initially - if (selection.xFixed === false) { - node.x = _this.canvas._XconvertDOMtoCanvas(_this.canvas._XconvertCanvasToDOM(selection.x) + deltaX); - } - // only move the node if it was not fixed initially - if (selection.yFixed === false) { - node.y = _this.canvas._YconvertDOMtoCanvas(_this.canvas._YconvertCanvasToDOM(selection.y) + deltaY); - } - }); + this.drag.pinched = true; + if (this.pinch.scale === undefined) { + this.pinch.scale = 1; + } - // start the simulation of the physics - _this.body.emitter.emit("startSimulation"); - })(); - } else { - // move the network - if (this.options.dragView === 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; + // TODO: enabled moving while pinching? + var scale = this.pinch.scale * event.scale; + this.zoom(scale, pointer); + } + }, { + key: "zoom", - this.body.view.translation = { x: this.drag.translation.x + diffX, y: this.drag.translation.y + diffY }; - this.body.emitter.emit("_redraw"); - } + /** + * 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 + */ + value: function zoom(scale, pointer) { + if (this.options.zoomView === true) { + var scaleOld = this.body.view.scale; + if (scale < 0.00001) { + scale = 0.00001; + } + if (scale > 10) { + scale = 10; } - }, - writable: true, - configurable: true - }, - onDragEnd: { - - /** - * handle drag start event - * @private - */ - value: function onDragEnd(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.options.fixed.x = s.xFixed; - s.node.options.fixed.y = s.yFixed; - }); - this.body.emitter.emit("startSimulation"); - } else { - this.body.emitter.emit("_requestRedraw"); + var preScaleDragPointer = undefined; + if (this.drag !== undefined) { + if (this.drag.dragging === true) { + preScaleDragPointer = this.canvas.DOMtoCanvas(this.drag.pointer); + } } + // + this.canvas.frame.canvas.clientHeight / 2 + var translation = this.body.view.translation; - this.body.emitter.emit("dragEnd", { nodeIds: this.selectionHandler.getSelection().nodes }); - }, - writable: true, - configurable: true - }, - onPinch: { + var scaleFrac = scale / scaleOld; + var tx = (1 - scaleFrac) * pointer.x + translation.x * scaleFrac; + var ty = (1 - scaleFrac) * pointer.y + translation.y * scaleFrac; + this.body.view.scale = scale; + this.body.view.translation = { x: tx, y: ty }; + if (preScaleDragPointer != undefined) { + var postScaleDragPointer = this.canvas.canvasToDOM(preScaleDragPointer); + this.drag.pointer.x = postScaleDragPointer.x; + this.drag.pointer.y = postScaleDragPointer.y; + } - /** - * Handle pinch event - * @param event - * @private - */ - value: function onPinch(event) { - var pointer = this.getPointer(event.center); + this.body.emitter.emit("_requestRedraw"); - this.drag.pinched = true; - if (this.pinch.scale === undefined) { - this.pinch.scale = 1; + if (scaleOld < scale) { + this.body.emitter.emit("zoom", { direction: "+" }); + } else { + this.body.emitter.emit("zoom", { direction: "-" }); } + } + } + }, { + key: "onMouseWheel", - // TODO: enabled moving while pinching? - var scale = this.pinch.scale * event.scale; - this.zoom(scale, pointer); - }, - writable: true, - configurable: true - }, - zoom: { + /** + * 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 + */ + value: function onMouseWheel(event) { + // retrieve delta + var delta = 0; + if (event.wheelDelta) { + /* IE/Opera. */ + delta = event.wheelDelta / 120; + } else if (event.detail) { + /* Mozilla case. */ + // In Mozilla, sign of delta is different than in IE. + // Also, delta is multiple of 3. + delta = -event.detail / 3; + } + // If delta is nonzero, handle it. + // Basically, delta is now positive if wheel was scrolled up, + // and negative, if wheel was scrolled down. + if (delta !== 0) { - /** - * 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 - */ - value: function zoom(scale, pointer) { - if (this.options.zoomView === true) { - var scaleOld = this.body.view.scale; - if (scale < 0.00001) { - scale = 0.00001; - } - if (scale > 10) { - scale = 10; - } + // calculate the new scale + var scale = this.body.view.scale; + var zoom = delta / 10; + if (delta < 0) { + zoom = zoom / (1 - zoom); + } + scale *= 1 + zoom; - var preScaleDragPointer = undefined; - if (this.drag !== undefined) { - if (this.drag.dragging === true) { - preScaleDragPointer = this.canvas.DOMtoCanvas(this.drag.pointer); - } - } - // + this.canvas.frame.canvas.clientHeight / 2 - var translation = this.body.view.translation; + // calculate the pointer location + var pointer = this.getPointer({ x: event.pageX, y: event.pageY }); - var scaleFrac = scale / scaleOld; - var tx = (1 - scaleFrac) * pointer.x + translation.x * scaleFrac; - var ty = (1 - scaleFrac) * pointer.y + translation.y * scaleFrac; + // apply the new scale + this.zoom(scale, pointer); + } - this.body.view.scale = scale; - this.body.view.translation = { x: tx, y: ty }; + // Prevent default actions caused by mouse wheel. + event.preventDefault(); + } + }, { + key: "onMouseMove", - if (preScaleDragPointer != undefined) { - var postScaleDragPointer = this.canvas.canvasToDOM(preScaleDragPointer); - this.drag.pointer.x = postScaleDragPointer.x; - this.drag.pointer.y = postScaleDragPointer.y; - } + /** + * Mouse move handler for checking whether the title moves over a node with a title. + * @param {Event} event + * @private + */ + value: function onMouseMove(event) { + var _this2 = this; - this.body.emitter.emit("_requestRedraw"); + var pointer = this.getPointer({ x: event.pageX, y: event.pageY }); + var popupVisible = false; - if (scaleOld < scale) { - this.body.emitter.emit("zoom", { direction: "+" }); - } else { - this.body.emitter.emit("zoom", { direction: "-" }); - } + // check if the previously selected node is still selected + if (this.popup !== undefined) { + if (this.popup.hidden === false) { + this._checkHidePopup(pointer); } - }, - writable: true, - configurable: true - }, - onMouseWheel: { - - - /** - * 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 - */ - value: function onMouseWheel(event) { - // retrieve delta - var delta = 0; - if (event.wheelDelta) { - /* IE/Opera. */ - delta = event.wheelDelta / 120; - } else if (event.detail) { - /* Mozilla case. */ - // In Mozilla, sign of delta is different than in IE. - // Also, delta is multiple of 3. - delta = -event.detail / 3; - } - - // If delta is nonzero, handle it. - // Basically, delta is now positive if wheel was scrolled up, - // and negative, if wheel was scrolled down. - if (delta !== 0) { - // calculate the new scale - var scale = this.body.view.scale; - var zoom = delta / 10; - if (delta < 0) { - zoom = zoom / (1 - zoom); - } - scale *= 1 + zoom; - - // calculate the pointer location - var pointer = this.getPointer({ x: event.pageX, y: event.pageY }); - // apply the new scale - this.zoom(scale, pointer); + // 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(); } + } - // Prevent default actions caused by mouse wheel. - event.preventDefault(); - }, - writable: true, - configurable: true - }, - onMouseMove: { + // if we bind the keyboard to the div, we have to highlight it to use it. This highlights it on mouse over. + if (this.options.keyboard.bindToWindow === false && this.options.keyboard.enabled === true) { + this.canvas.frame.focus(); + } + // start a timeout that will check if the mouse is positioned above an element + if (popupVisible === false) { + if (this.popupTimer !== undefined) { + clearInterval(this.popupTimer); // stop any running calculationTimer + this.popupTimer = undefined; + } + if (!this.drag.dragging) { + this.popupTimer = setTimeout(function () { + return _this2._checkShowPopup(pointer); + }, this.options.tooltip.delay); + } + } /** - * Mouse move handler for checking whether the title moves over a node with a title. - * @param {Event} event - * @private - */ - value: function onMouseMove(event) { - var _this = this; - var pointer = this.getPointer({ x: event.pageX, y: event.pageY }); - var popupVisible = false; - - // check if the previously selected node is still selected - if (this.popup !== undefined) { - if (this.popup.hidden === false) { - this._checkHidePopup(pointer); - } - - // 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(); + * Adding hover highlights + */ + if (this.options.hoverEnabled === true) { + // removing all hover highlights + for (var edgeId in this.hoverObj.edges) { + if (this.hoverObj.edges.hasOwnProperty(edgeId)) { + this.hoverObj.edges[edgeId].hover = false; + delete this.hoverObj.edges[edgeId]; } } - // if we bind the keyboard to the div, we have to highlight it to use it. This highlights it on mouse over. - if (this.options.keyboard.bindToWindow === false && this.options.keyboard.enabled === true) { - this.canvas.frame.focus(); + // adding hover highlights + var obj = this.selectionHandler.getNodeAt(pointer); + if (obj === undefined) { + obj = this.selectionHandler.getEdgeAt(pointer); } - - // start a timeout that will check if the mouse is positioned above an element - if (popupVisible === false) { - if (this.popupTimer !== undefined) { - clearInterval(this.popupTimer); // stop any running calculationTimer - this.popupTimer = undefined; - } - if (!this.drag.dragging) { - this.popupTimer = setTimeout(function () { - return _this._checkShowPopup(pointer); - }, this.options.tooltip.delay); - } + if (obj != undefined) { + this.selectionHandler.hoverObject(obj); } - /** - * Adding hover highlights - */ - if (this.options.hoverEnabled === 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]; - } - } - - // adding hover highlights - var obj = this.selectionHandler.getNodeAt(pointer); - if (obj === undefined) { - obj = this.selectionHandler.getEdgeAt(pointer); - } - if (obj != undefined) { - this.selectionHandler.hoverObject(obj); - } - - // removing all node hover highlights except for the selected one. - for (var nodeId in this.hoverObj.nodes) { - if (this.hoverObj.nodes.hasOwnProperty(nodeId)) { - if (obj instanceof Node && obj.id != nodeId || obj instanceof Edge || obj === undefined) { - this.selectionHandler.blurObject(this.hoverObj.nodes[nodeId]); - delete this.hoverObj.nodes[nodeId]; - } + // 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 === undefined) { + this.selectionHandler.blurObject(this.hoverObj.nodes[nodeId]); + delete this.hoverObj.nodes[nodeId]; } } - this.body.emitter.emit("_requestRedraw"); } - }, - writable: true, - configurable: true - }, - _checkShowPopup: { - + this.body.emitter.emit("_requestRedraw"); + } + } + }, { + key: "_checkShowPopup", + /** + * 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 + */ + value: function _checkShowPopup(pointer) { + var x = this.canvas._XconvertDOMtoCanvas(pointer.x); + var y = this.canvas._YconvertDOMtoCanvas(pointer.y); + var pointerObj = { + left: x, + top: y, + right: x, + bottom: y + }; - /** - * 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 - */ - value: function _checkShowPopup(pointer) { - var x = this.canvas._XconvertDOMtoCanvas(pointer.x); - var y = this.canvas._YconvertDOMtoCanvas(pointer.y); - var pointerObj = { - left: x, - top: y, - right: x, - bottom: y - }; + var previousPopupObjId = this.popupObj === undefined ? undefined : this.popupObj.id; + var nodeUnderCursor = false; + var popupType = "node"; - var previousPopupObjId = this.popupObj === undefined ? undefined : this.popupObj.id; - var nodeUnderCursor = false; - var popupType = "node"; - - // check if a node is under the cursor. - if (this.popupObj === undefined) { - // search the nodes for overlap, select the top one in case of multiple nodes - var nodeIndices = this.body.nodeIndices; - var nodes = this.body.nodes; - var node = undefined; - var overlappingNodes = []; - for (var i = 0; i < nodeIndices.length; i++) { - node = nodes[nodeIndices[i]]; - if (node.isOverlappingWith(pointerObj) === true) { - if (node.getTitle() !== undefined) { - overlappingNodes.push(nodeIndices[i]); - } + // check if a node is under the cursor. + if (this.popupObj === undefined) { + // search the nodes for overlap, select the top one in case of multiple nodes + var nodeIndices = this.body.nodeIndices; + var nodes = this.body.nodes; + var node = undefined; + var overlappingNodes = []; + for (var i = 0; i < nodeIndices.length; i++) { + node = nodes[nodeIndices[i]]; + if (node.isOverlappingWith(pointerObj) === true) { + if (node.getTitle() !== undefined) { + overlappingNodes.push(nodeIndices[i]); } } + } - 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 = nodes[overlappingNodes[overlappingNodes.length - 1]]; - // if you hover over a node, the title of the edge is not supposed to be shown. - nodeUnderCursor = true; - } + 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 = nodes[overlappingNodes[overlappingNodes.length - 1]]; + // if you hover over a node, the title of the edge is not supposed to be shown. + nodeUnderCursor = true; } + } - if (this.popupObj === undefined && nodeUnderCursor === false) { - // search the edges for overlap - var edgeIndices = this.body.edgeIndices; - var edges = this.body.edges; - var edge = undefined; - var overlappingEdges = []; - for (var i = 0; i < edgeIndices.length; i++) { - edge = edges[edgeIndices[i]]; - if (edge.isOverlappingWith(pointerObj) === true) { - if (edge.connected === true && edge.getTitle() !== undefined) { - overlappingEdges.push(edgeIndices[i]); - } + if (this.popupObj === undefined && nodeUnderCursor === false) { + // search the edges for overlap + var edgeIndices = this.body.edgeIndices; + var edges = this.body.edges; + var edge = undefined; + var overlappingEdges = []; + for (var i = 0; i < edgeIndices.length; i++) { + edge = edges[edgeIndices[i]]; + if (edge.isOverlappingWith(pointerObj) === true) { + if (edge.connected === true && edge.getTitle() !== undefined) { + overlappingEdges.push(edgeIndices[i]); } } + } - if (overlappingEdges.length > 0) { - this.popupObj = edges[overlappingEdges[overlappingEdges.length - 1]]; - popupType = "edge"; - } + if (overlappingEdges.length > 0) { + this.popupObj = edges[overlappingEdges[overlappingEdges.length - 1]]; + popupType = "edge"; } + } - if (this.popupObj !== undefined) { - // show popup message window - if (this.popupObj.id !== previousPopupObjId) { - if (this.popup === undefined) { - this.popup = new Popup(this.frame, this.options.tooltip); - } + if (this.popupObj !== undefined) { + // show popup message window + if (this.popupObj.id !== previousPopupObjId) { + if (this.popup === undefined) { + this.popup = new _Popup2["default"](this.frame, this.options.tooltip); + } - this.popup.popupTargetType = popupType; - this.popup.popupTargetId = this.popupObj.id; + this.popup.popupTargetType = popupType; + this.popup.popupTargetId = this.popupObj.id; - // 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(); - } + // 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(); } - }, - writable: true, - configurable: true - }, - _checkHidePopup: { - + } else { + if (this.popup) { + this.popup.hide(); + } + } + } + }, { + key: "_checkHidePopup", - /** - * 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 - */ - value: function _checkHidePopup(pointer) { - var x = this.canvas._XconvertDOMtoCanvas(pointer.x); - var y = this.canvas._YconvertDOMtoCanvas(pointer.y); - var pointerObj = { - left: x, - top: y, - right: x, - bottom: y - }; + /** + * 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 + */ + value: function _checkHidePopup(pointer) { + var x = this.canvas._XconvertDOMtoCanvas(pointer.x); + var y = this.canvas._YconvertDOMtoCanvas(pointer.y); + var pointerObj = { + left: x, + top: y, + right: x, + bottom: y + }; - var stillOnObj = false; - if (this.popup.popupTargetType === "node") { - if (this.body.nodes[this.popup.popupTargetId] !== undefined) { - stillOnObj = this.body.nodes[this.popup.popupTargetId].isOverlappingWith(pointerObj); + var stillOnObj = false; + if (this.popup.popupTargetType === "node") { + if (this.body.nodes[this.popup.popupTargetId] !== undefined) { + stillOnObj = this.body.nodes[this.popup.popupTargetId].isOverlappingWith(pointerObj); - // if the mouse is still one the node, we have to check if it is not also on one that is drawn on top of it. - // we initially only check stillOnObj because this is much faster. - if (stillOnObj === true) { - var overNode = this.selectionHandler.getNodeAt(pointer); - stillOnObj = overNode.id === this.popup.popupTargetId; - } + // if the mouse is still one the node, we have to check if it is not also on one that is drawn on top of it. + // we initially only check stillOnObj because this is much faster. + if (stillOnObj === true) { + var overNode = this.selectionHandler.getNodeAt(pointer); + stillOnObj = overNode.id === this.popup.popupTargetId; } - } else { - if (this.selectionHandler.getNodeAt(pointer) === undefined) { - if (this.body.edges[this.popup.popupTargetId] !== undefined) { - stillOnObj = this.body.edges[this.popup.popupTargetId].isOverlappingWith(pointerObj); - } + } + } else { + if (this.selectionHandler.getNodeAt(pointer) === undefined) { + if (this.body.edges[this.popup.popupTargetId] !== undefined) { + stillOnObj = this.body.edges[this.popup.popupTargetId].isOverlappingWith(pointerObj); } } + } - - if (stillOnObj === false) { - this.popupObj = undefined; - this.popup.hide(); - } - }, - writable: true, - configurable: true + if (stillOnObj === false) { + this.popupObj = undefined; + this.popup.hide(); + } } - }); + }]); return InteractionHandler; })(); - module.exports = InteractionHandler; + exports["default"] = InteractionHandler; + module.exports = exports["default"]; /***/ }, -/* 59 */ +/* 58 */ /***/ function(module, exports, __webpack_require__) { "use strict"; - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; - var Node = __webpack_require__(80); + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + Object.defineProperty(exports, "__esModule", { + value: true + }); + var Node = __webpack_require__(67); var util = __webpack_require__(1); var SelectionHandler = (function () { function SelectionHandler(body, canvas) { var _this = this; + _classCallCheck(this, SelectionHandler); this.body = body; @@ -21866,739 +22278,650 @@ return /******/ (function(modules) { // webpackBootstrap }); } - _prototypeProperties(SelectionHandler, null, { - setOptions: { - value: function setOptions(options) { - if (options !== undefined) { - util.deepExtend(this.options, options); - } - }, - writable: true, - configurable: true - }, - selectOnPoint: { - + _createClass(SelectionHandler, [{ + key: "setOptions", + value: function setOptions(options) { + if (options !== undefined) { + util.deepExtend(this.options, options); + } + } + }, { + key: "selectOnPoint", - /** - * handles the selection part of the tap; - * - * @param {Object} pointer - * @private - */ - value: function selectOnPoint(pointer) { - var selected = false; - if (this.options.select === true) { - this.unselectAll(); - var obj = this.getNodeAt(pointer) || this.getEdgeAt(pointer);; - if (obj !== undefined) { - selected = this.selectObject(obj); - } - this.body.emitter.emit("_requestRedraw"); + /** + * handles the selection part of the tap; + * + * @param {Object} pointer + * @private + */ + value: function selectOnPoint(pointer) { + var selected = false; + if (this.options.select === true) { + this.unselectAll(); + var obj = this.getNodeAt(pointer) || this.getEdgeAt(pointer);; + if (obj !== undefined) { + selected = this.selectObject(obj); } - return selected; - }, - writable: true, - configurable: true - }, - selectAdditionalOnPoint: { - value: function selectAdditionalOnPoint(pointer) { - var selectionChanged = false; - if (this.options.select === true) { - var obj = this.getNodeAt(pointer) || this.getEdgeAt(pointer);; - - if (obj !== undefined) { - selectionChanged = true; - if (obj.isSelected() === true) { - this.deselectObject(obj); - } else { - this.selectObject(obj); - } + this.body.emitter.emit("_requestRedraw"); + } + return selected; + } + }, { + key: "selectAdditionalOnPoint", + value: function selectAdditionalOnPoint(pointer) { + var selectionChanged = false; + if (this.options.select === true) { + var obj = this.getNodeAt(pointer) || this.getEdgeAt(pointer);; - this.body.emitter.emit("_requestRedraw"); - } - } - return selectionChanged; - }, - writable: true, - configurable: true - }, - _generateClickEvent: { - value: function _generateClickEvent(eventType, pointer) { - var properties = this.getSelection(); - properties.pointer = { - DOM: { x: pointer.x, y: pointer.y }, - canvas: this.canvas.DOMtoCanvas(pointer) - }; - this.body.emitter.emit(eventType, properties); - }, - writable: true, - configurable: true - }, - selectObject: { - value: function selectObject(obj) { if (obj !== undefined) { - if (obj instanceof Node) { - if (this.options.selectConnectedEdges === true || this.forceSelectEdges === true) { - this._selectConnectedEdges(obj); - } + selectionChanged = true; + if (obj.isSelected() === true) { + this.deselectObject(obj); + } else { + this.selectObject(obj); } - obj.select(); - this._addToSelection(obj); - return true; - } - return false; - }, - writable: true, - configurable: true - }, - deselectObject: { - value: function deselectObject(obj) { - if (obj.isSelected() === true) { - obj.selected = false; - this._removeFromSelection(obj); - } - }, - writable: true, - configurable: true - }, - _getAllNodesOverlappingWith: { - - - /** - * 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 - */ - value: function _getAllNodesOverlappingWith(object) { - var overlappingNodes = []; - var nodes = this.body.nodes; - for (var i = 0; i < this.body.nodeIndices.length; i++) { - var nodeId = this.body.nodeIndices[i]; - if (nodes[nodeId].isOverlappingWith(object)) { - overlappingNodes.push(nodeId); + this.body.emitter.emit("_requestRedraw"); + } + } + return selectionChanged; + } + }, { + key: "_generateClickEvent", + value: function _generateClickEvent(eventType, pointer) { + var properties = this.getSelection(); + properties.pointer = { + DOM: { x: pointer.x, y: pointer.y }, + canvas: this.canvas.DOMtoCanvas(pointer) + }; + this.body.emitter.emit(eventType, properties); + } + }, { + key: "selectObject", + value: function selectObject(obj) { + if (obj !== undefined) { + if (obj instanceof Node) { + if (this.options.selectConnectedEdges === true || this.forceSelectEdges === true) { + this._selectConnectedEdges(obj); } } - return overlappingNodes; - }, - writable: true, - configurable: true - }, - _pointerToPositionObject: { - + obj.select(); + this._addToSelection(obj); + return true; + } + return false; + } + }, { + key: "deselectObject", + value: function deselectObject(obj) { + if (obj.isSelected() === true) { + obj.selected = false; + this._removeFromSelection(obj); + } + } + }, { + key: "_getAllNodesOverlappingWith", - /** - * Return a position object in canvasspace from a single point in screenspace - * - * @param pointer - * @returns {{left: number, top: number, right: number, bottom: number}} - * @private - */ - value: function _pointerToPositionObject(pointer) { - var canvasPos = this.canvas.DOMtoCanvas(pointer); - return { - left: canvasPos.x - 1, - top: canvasPos.y + 1, - right: canvasPos.x + 1, - bottom: canvasPos.y - 1 - }; - }, - writable: true, - configurable: true - }, - getNodeAt: { + /** + * 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 + */ + value: function _getAllNodesOverlappingWith(object) { + var overlappingNodes = []; + var nodes = this.body.nodes; + for (var i = 0; i < this.body.nodeIndices.length; i++) { + var nodeId = this.body.nodeIndices[i]; + if (nodes[nodeId].isOverlappingWith(object)) { + overlappingNodes.push(nodeId); + } + } + return overlappingNodes; + } + }, { + key: "_pointerToPositionObject", + /** + * Return a position object in canvasspace from a single point in screenspace + * + * @param pointer + * @returns {{left: number, top: number, right: number, bottom: number}} + * @private + */ + value: function _pointerToPositionObject(pointer) { + var canvasPos = this.canvas.DOMtoCanvas(pointer); + return { + left: canvasPos.x - 1, + top: canvasPos.y + 1, + right: canvasPos.x + 1, + bottom: canvasPos.y - 1 + }; + } + }, { + key: "getNodeAt", - /** - * Get the top node at the a specific point (like a click) - * - * @param {{x: Number, y: Number}} pointer - * @return {Node | undefined} node - * @private - */ - value: function getNodeAt(pointer) { - // we first check if this is an navigation controls element - var positionObject = this._pointerToPositionObject(pointer); - var overlappingNodes = this._getAllNodesOverlappingWith(positionObject); + /** + * Get the top node at the a specific point (like a click) + * + * @param {{x: Number, y: Number}} pointer + * @return {Node | undefined} node + * @private + */ + value: function getNodeAt(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.body.nodes[overlappingNodes[overlappingNodes.length - 1]]; + } else { + return undefined; + } + } + }, { + key: "_getEdgesOverlappingWith", - // 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.body.nodes[overlappingNodes[overlappingNodes.length - 1]]; - } else { - return undefined; + /** + * 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 + */ + value: function _getEdgesOverlappingWith(object, overlappingEdges) { + var edges = this.body.edges; + for (var i = 0; i < this.body.edgeIndices.length; i++) { + var edgeId = this.body.edgeIndices[i]; + if (edges[edgeId].isOverlappingWith(object)) { + overlappingEdges.push(edgeId); } - }, - writable: true, - configurable: true - }, - _getEdgesOverlappingWith: { + } + } + }, { + key: "_getAllEdgesOverlappingWith", + /** + * 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 + */ + value: function _getAllEdgesOverlappingWith(object) { + var overlappingEdges = []; + this._getEdgesOverlappingWith(object, overlappingEdges); + return overlappingEdges; + } + }, { + key: "getEdgeAt", - /** - * 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 - */ - value: function _getEdgesOverlappingWith(object, overlappingEdges) { - var edges = this.body.edges; - for (var i = 0; i < this.body.edgeIndices.length; i++) { - var edgeId = this.body.edgeIndices[i]; - if (edges[edgeId].isOverlappingWith(object)) { - overlappingEdges.push(edgeId); - } - } - }, - writable: true, - configurable: true - }, - _getAllEdgesOverlappingWith: { + /** + * 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 {undefined} + * @private + */ + value: function getEdgeAt(pointer) { + var positionObject = this._pointerToPositionObject(pointer); + var overlappingEdges = this._getAllEdgesOverlappingWith(positionObject); + if (overlappingEdges.length > 0) { + return this.body.edges[overlappingEdges[overlappingEdges.length - 1]]; + } else { + return undefined; + } + } + }, { + key: "_addToSelection", - /** - * 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 - */ - value: function _getAllEdgesOverlappingWith(object) { - var overlappingEdges = []; - this._getEdgesOverlappingWith(object, overlappingEdges); - return overlappingEdges; - }, - writable: true, - configurable: true - }, - getEdgeAt: { + /** + * Add object to the selection array. + * + * @param obj + * @private + */ + value: function _addToSelection(obj) { + if (obj instanceof Node) { + this.selectionObj.nodes[obj.id] = obj; + } else { + this.selectionObj.edges[obj.id] = obj; + } + } + }, { + key: "_addToHover", + /** + * Add object to the selection array. + * + * @param obj + * @private + */ + value: function _addToHover(obj) { + if (obj instanceof Node) { + this.hoverObj.nodes[obj.id] = obj; + } else { + this.hoverObj.edges[obj.id] = obj; + } + } + }, { + key: "_removeFromSelection", - /** - * 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 {undefined} - * @private - */ - value: function getEdgeAt(pointer) { - var positionObject = this._pointerToPositionObject(pointer); - var overlappingEdges = this._getAllEdgesOverlappingWith(positionObject); + /** + * Remove a single option from selection. + * + * @param {Object} obj + * @private + */ + value: function _removeFromSelection(obj) { + if (obj instanceof Node) { + delete this.selectionObj.nodes[obj.id]; + } else { + delete this.selectionObj.edges[obj.id]; + } + } + }, { + key: "unselectAll", - if (overlappingEdges.length > 0) { - return this.body.edges[overlappingEdges[overlappingEdges.length - 1]]; - } else { - return undefined; + /** + * Unselect all. The selectionObj is useful for this. + * + * @private + */ + value: function unselectAll() { + for (var nodeId in this.selectionObj.nodes) { + if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { + this.selectionObj.nodes[nodeId].unselect(); } - }, - writable: true, - configurable: true - }, - _addToSelection: { + } + for (var edgeId in this.selectionObj.edges) { + if (this.selectionObj.edges.hasOwnProperty(edgeId)) { + this.selectionObj.edges[edgeId].unselect(); + } + } + this.selectionObj = { nodes: {}, edges: {} }; + } + }, { + key: "_getSelectedNodeCount", - /** - * Add object to the selection array. - * - * @param obj - * @private - */ - value: function _addToSelection(obj) { - if (obj instanceof Node) { - this.selectionObj.nodes[obj.id] = obj; - } else { - this.selectionObj.edges[obj.id] = obj; + /** + * return the number of selected nodes + * + * @returns {number} + * @private + */ + value: function _getSelectedNodeCount() { + var count = 0; + for (var nodeId in this.selectionObj.nodes) { + if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { + count += 1; } - }, - writable: true, - configurable: true - }, - _addToHover: { + } + return count; + } + }, { + key: "_getSelectedNode", - /** - * Add object to the selection array. - * - * @param obj - * @private - */ - value: function _addToHover(obj) { - if (obj instanceof Node) { - this.hoverObj.nodes[obj.id] = obj; - } else { - this.hoverObj.edges[obj.id] = obj; + /** + * return the selected node + * + * @returns {number} + * @private + */ + value: function _getSelectedNode() { + for (var nodeId in this.selectionObj.nodes) { + if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { + return this.selectionObj.nodes[nodeId]; } - }, - writable: true, - configurable: true - }, - _removeFromSelection: { + } + return undefined; + } + }, { + key: "_getSelectedEdge", + /** + * return the selected edge + * + * @returns {number} + * @private + */ + value: function _getSelectedEdge() { + for (var edgeId in this.selectionObj.edges) { + if (this.selectionObj.edges.hasOwnProperty(edgeId)) { + return this.selectionObj.edges[edgeId]; + } + } + return undefined; + } + }, { + key: "_getSelectedEdgeCount", - /** - * Remove a single option from selection. - * - * @param {Object} obj - * @private - */ - value: function _removeFromSelection(obj) { - if (obj instanceof Node) { - delete this.selectionObj.nodes[obj.id]; - } else { - delete this.selectionObj.edges[obj.id]; + /** + * return the number of selected edges + * + * @returns {number} + * @private + */ + value: function _getSelectedEdgeCount() { + var count = 0; + for (var edgeId in this.selectionObj.edges) { + if (this.selectionObj.edges.hasOwnProperty(edgeId)) { + count += 1; } - }, - writable: true, - configurable: true - }, - unselectAll: { + } + return count; + } + }, { + key: "_getSelectedObjectCount", - /** - * Unselect all. The selectionObj is useful for this. - * - * @private - */ - value: function unselectAll() { - for (var nodeId in this.selectionObj.nodes) { - if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { - this.selectionObj.nodes[nodeId].unselect(); - } + /** + * return the number of selected objects. + * + * @returns {number} + * @private + */ + value: function _getSelectedObjectCount() { + 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)) { - this.selectionObj.edges[edgeId].unselect(); - } + } + for (var edgeId in this.selectionObj.edges) { + if (this.selectionObj.edges.hasOwnProperty(edgeId)) { + count += 1; } + } + return count; + } + }, { + key: "_selectionIsEmpty", - this.selectionObj = { nodes: {}, edges: {} }; - }, - writable: true, - configurable: true - }, - _getSelectedNodeCount: { - - - /** - * return the number of selected nodes - * - * @returns {number} - * @private - */ - value: function _getSelectedNodeCount() { - var count = 0; - for (var nodeId in this.selectionObj.nodes) { - if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { - count += 1; - } + /** + * Check if anything is selected + * + * @returns {boolean} + * @private + */ + value: function _selectionIsEmpty() { + for (var nodeId in this.selectionObj.nodes) { + if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { + return false; } - return count; - }, - writable: true, - configurable: true - }, - _getSelectedNode: { + } + for (var edgeId in this.selectionObj.edges) { + if (this.selectionObj.edges.hasOwnProperty(edgeId)) { + return false; + } + } + return true; + } + }, { + key: "_clusterInSelection", - /** - * return the selected node - * - * @returns {number} - * @private - */ - value: function _getSelectedNode() { - for (var nodeId in this.selectionObj.nodes) { - if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { - return this.selectionObj.nodes[nodeId]; + /** + * check if one of the selected nodes is a cluster. + * + * @returns {boolean} + * @private + */ + value: function _clusterInSelection() { + for (var nodeId in this.selectionObj.nodes) { + if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { + if (this.selectionObj.nodes[nodeId].clusterSize > 1) { + return true; } } - return undefined; - }, - writable: true, - configurable: true - }, - _getSelectedEdge: { - - /** - * return the selected edge - * - * @returns {number} - * @private - */ - value: function _getSelectedEdge() { - for (var edgeId in this.selectionObj.edges) { - if (this.selectionObj.edges.hasOwnProperty(edgeId)) { - return this.selectionObj.edges[edgeId]; - } - } - return undefined; - }, - writable: true, - configurable: true - }, - _getSelectedEdgeCount: { + } + return false; + } + }, { + key: "_selectConnectedEdges", + /** + * select the edges connected to the node that is being selected + * + * @param {Node} node + * @private + */ + value: function _selectConnectedEdges(node) { + for (var i = 0; i < node.edges.length; i++) { + var edge = node.edges[i]; + edge.select(); + this._addToSelection(edge); + } + } + }, { + key: "_hoverConnectedEdges", - /** - * return the number of selected edges - * - * @returns {number} - * @private - */ - value: function _getSelectedEdgeCount() { - var count = 0; - for (var edgeId in this.selectionObj.edges) { - if (this.selectionObj.edges.hasOwnProperty(edgeId)) { - count += 1; - } - } - return count; - }, - writable: true, - configurable: true - }, - _getSelectedObjectCount: { + /** + * select the edges connected to the node that is being selected + * + * @param {Node} node + * @private + */ + value: function _hoverConnectedEdges(node) { + for (var i = 0; i < node.edges.length; i++) { + var edge = node.edges[i]; + edge.hover = true; + this._addToHover(edge); + } + } + }, { + key: "_unselectConnectedEdges", + /** + * unselect the edges connected to the node that is being selected + * + * @param {Node} node + * @private + */ + value: function _unselectConnectedEdges(node) { + for (var i = 0; i < node.edges.length; i++) { + var edge = node.edges[i]; + edge.unselect(); + this._removeFromSelection(edge); + } + } + }, { + key: "blurObject", - /** - * return the number of selected objects. - * - * @returns {number} - * @private - */ - value: function _getSelectedObjectCount() { - 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; - }, - writable: true, - configurable: true - }, - _selectionIsEmpty: { + /** + * 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 + */ + value: function blurObject(object) { + if (object.hover === true) { + object.hover = false; + this.body.emitter.emit("blurNode", { node: object.id }); + } + } + }, { + key: "hoverObject", - /** - * Check if anything is selected - * - * @returns {boolean} - * @private - */ - value: function _selectionIsEmpty() { - 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; - } + /** + * 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 + */ + value: function hoverObject(object) { + if (object.hover === false) { + object.hover = true; + this._addToHover(object); + if (object instanceof Node) { + this.body.emitter.emit("hoverNode", { node: object.id }); } - return true; - }, - writable: true, - configurable: true - }, - _clusterInSelection: { + } + if (object instanceof Node) { + this._hoverConnectedEdges(object); + } + } + }, { + key: "getSelection", + /** + * + * retrieve the currently selected objects + * @return {{nodes: Array., edges: Array.}} selection + */ + value: function getSelection() { + var nodeIds = this.getSelectedNodes(); + var edgeIds = this.getSelectedEdges(); + return { nodes: nodeIds, edges: edgeIds }; + } + }, { + key: "getSelectedNodes", - /** - * check if one of the selected nodes is a cluster. - * - * @returns {boolean} - * @private - */ - value: function _clusterInSelection() { + /** + * + * retrieve the currently selected nodes + * @return {String[]} selection An array with the ids of the + * selected nodes. + */ + value: function getSelectedNodes() { + var idArray = []; + if (this.options.select === true) { for (var nodeId in this.selectionObj.nodes) { if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { - if (this.selectionObj.nodes[nodeId].clusterSize > 1) { - return true; - } - } - } - return false; - }, - writable: true, - configurable: true - }, - _selectConnectedEdges: { - - /** - * select the edges connected to the node that is being selected - * - * @param {Node} node - * @private - */ - value: function _selectConnectedEdges(node) { - for (var i = 0; i < node.edges.length; i++) { - var edge = node.edges[i]; - edge.select(); - this._addToSelection(edge); - } - }, - writable: true, - configurable: true - }, - _hoverConnectedEdges: { - - /** - * select the edges connected to the node that is being selected - * - * @param {Node} node - * @private - */ - value: function _hoverConnectedEdges(node) { - for (var i = 0; i < node.edges.length; i++) { - var edge = node.edges[i]; - edge.hover = true; - this._addToHover(edge); - } - }, - writable: true, - configurable: true - }, - _unselectConnectedEdges: { - - - /** - * unselect the edges connected to the node that is being selected - * - * @param {Node} node - * @private - */ - value: function _unselectConnectedEdges(node) { - for (var i = 0; i < node.edges.length; i++) { - var edge = node.edges[i]; - edge.unselect(); - this._removeFromSelection(edge); - } - }, - writable: true, - configurable: true - }, - blurObject: { - - - - - - - /** - * 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 - */ - value: function blurObject(object) { - if (object.hover === true) { - object.hover = false; - this.body.emitter.emit("blurNode", { node: object.id }); - } - }, - writable: true, - configurable: true - }, - hoverObject: { - - /** - * 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 - */ - value: function hoverObject(object) { - if (object.hover === false) { - object.hover = true; - this._addToHover(object); - if (object instanceof Node) { - this.body.emitter.emit("hoverNode", { node: object.id }); - } - } - if (object instanceof Node) { - this._hoverConnectedEdges(object); - } - }, - writable: true, - configurable: true - }, - getSelection: { - - - - - /** - * - * retrieve the currently selected objects - * @return {{nodes: Array., edges: Array.}} selection - */ - value: function getSelection() { - var nodeIds = this.getSelectedNodes(); - var edgeIds = this.getSelectedEdges(); - return { nodes: nodeIds, edges: edgeIds }; - }, - writable: true, - configurable: true - }, - getSelectedNodes: { - - /** - * - * retrieve the currently selected nodes - * @return {String[]} selection An array with the ids of the - * selected nodes. - */ - value: function getSelectedNodes() { - var idArray = []; - if (this.options.select === true) { - for (var nodeId in this.selectionObj.nodes) { - if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { - idArray.push(nodeId); - } + idArray.push(nodeId); } } - return idArray; - }, - writable: true, - configurable: true - }, - getSelectedEdges: { + } + return idArray; + } + }, { + key: "getSelectedEdges", - /** - * - * retrieve the currently selected edges - * @return {Array} selection An array with the ids of the - * selected nodes. - */ - value: function getSelectedEdges() { - var idArray = []; - if (this.options.select === true) { - for (var edgeId in this.selectionObj.edges) { - if (this.selectionObj.edges.hasOwnProperty(edgeId)) { - idArray.push(edgeId); - } + /** + * + * retrieve the currently selected edges + * @return {Array} selection An array with the ids of the + * selected nodes. + */ + value: function getSelectedEdges() { + var idArray = []; + if (this.options.select === true) { + for (var edgeId in this.selectionObj.edges) { + if (this.selectionObj.edges.hasOwnProperty(edgeId)) { + idArray.push(edgeId); } } - return idArray; - }, - writable: true, - configurable: true - }, - selectNodes: { - + } + return idArray; + } + }, { + key: "selectNodes", - /** - * 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] - */ - value: function selectNodes(selection, highlightEdges) { - var i, iMax, id; + /** + * 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] + */ + value: function selectNodes(selection, highlightEdges) { + var i, iMax, id; - if (!selection || selection.length === undefined) throw "Selection must be an array with ids"; + if (!selection || selection.length === undefined) throw "Selection must be an array with ids"; - // first unselect any selected node - this.unselectAll(true); + // first unselect any selected node + this.unselectAll(true); - for (i = 0, iMax = selection.length; i < iMax; i++) { - id = selection[i]; + for (i = 0, iMax = selection.length; i < iMax; i++) { + id = selection[i]; - var node = this.body.nodes[id]; - if (!node) { - throw new RangeError("Node with id \"" + id + "\" not found"); - } - this._selectObject(node, true, true, highlightEdges, true); + var node = this.body.nodes[id]; + if (!node) { + throw new RangeError("Node with id \"" + id + "\" not found"); } - this.redraw(); - }, - writable: true, - configurable: true - }, - selectEdges: { - + this._selectObject(node, true, true, highlightEdges, true); + } + this.redraw(); + } + }, { + key: "selectEdges", - /** - * select zero or more edges - * @param {Number[] | String[]} selection An array with the ids of the - * selected nodes. - */ - value: function selectEdges(selection) { - var i, iMax, id; + /** + * select zero or more edges + * @param {Number[] | String[]} selection An array with the ids of the + * selected nodes. + */ + value: function selectEdges(selection) { + var i, iMax, id; - if (!selection || selection.length === undefined) throw "Selection must be an array with ids"; + if (!selection || selection.length === undefined) throw "Selection must be an array with ids"; - // first unselect any selected node - this.unselectAll(true); + // first unselect any selected node + this.unselectAll(true); - for (i = 0, iMax = selection.length; i < iMax; i++) { - id = selection[i]; + for (i = 0, iMax = selection.length; i < iMax; i++) { + id = selection[i]; - var edge = this.body.edges[id]; - if (!edge) { - throw new RangeError("Edge with id \"" + id + "\" not found"); - } - this._selectObject(edge, true, true, false, true); + var edge = this.body.edges[id]; + if (!edge) { + throw new RangeError("Edge with id \"" + id + "\" not found"); } - this.redraw(); - }, - writable: true, - configurable: true - }, - updateSelection: { + this._selectObject(edge, true, true, false, true); + } + this.redraw(); + } + }, { + key: "updateSelection", - /** - * Validate the selection: remove ids of nodes which no longer exist - * @private - */ - value: function updateSelection() { - for (var nodeId in this.selectionObj.nodes) { - if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { - if (!this.body.nodes.hasOwnProperty(nodeId)) { - delete this.selectionObj.nodes[nodeId]; - } + /** + * Validate the selection: remove ids of nodes which no longer exist + * @private + */ + value: function updateSelection() { + for (var nodeId in this.selectionObj.nodes) { + if (this.selectionObj.nodes.hasOwnProperty(nodeId)) { + if (!this.body.nodes.hasOwnProperty(nodeId)) { + delete this.selectionObj.nodes[nodeId]; } } - for (var edgeId in this.selectionObj.edges) { - if (this.selectionObj.edges.hasOwnProperty(edgeId)) { - if (!this.body.edges.hasOwnProperty(edgeId)) { - delete this.selectionObj.edges[edgeId]; - } + } + for (var edgeId in this.selectionObj.edges) { + if (this.selectionObj.edges.hasOwnProperty(edgeId)) { + if (!this.body.edges.hasOwnProperty(edgeId)) { + delete this.selectionObj.edges[edgeId]; } } - }, - writable: true, - configurable: true + } } - }); + }]); return SelectionHandler; })(); - module.exports = SelectionHandler; + exports["default"] = SelectionHandler; + module.exports = exports["default"]; /***/ }, -/* 60 */ +/* 59 */ /***/ function(module, exports, __webpack_require__) { "use strict"; - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + Object.defineProperty(exports, "__esModule", { + value: true + }); var util = __webpack_require__(1); var LayoutEngine = (function () { function LayoutEngine(body) { var _this = this; + _classCallCheck(this, LayoutEngine); this.body = body; @@ -22624,476 +22947,445 @@ return /******/ (function(modules) { // webpackBootstrap }); } - _prototypeProperties(LayoutEngine, null, { - setOptions: { - value: function setOptions(options, allOptions) { - if (options !== undefined) { - util.mergeOptions(this.options, options, "hierarchical"); - if (options.randomSeed !== undefined) { - this.randomSeed = options.randomSeed; - } - - if (this.options.hierarchical.enabled === true) { - // make sure the level seperation is the right way up - if (this.options.hierarchical.direction === "RL" || this.options.hierarchical.direction === "DU") { - if (this.options.hierarchical.levelSeparation > 0) { - this.options.hierarchical.levelSeparation *= -1; - } - } else { - if (this.options.hierarchical.levelSeparation < 0) { - this.options.hierarchical.levelSeparation *= -1; - } - } - - // because the hierarchical system needs it's own physics and smooth curve settings, we adapt the other options if needed. - return this.adaptAllOptions(allOptions); - } + _createClass(LayoutEngine, [{ + key: "setOptions", + value: function setOptions(options, allOptions) { + if (options !== undefined) { + util.mergeOptions(this.options, options, "hierarchical"); + if (options.randomSeed !== undefined) { + this.randomSeed = options.randomSeed; } - return allOptions; - }, - writable: true, - configurable: true - }, - adaptAllOptions: { - value: function adaptAllOptions(allOptions) { - if (this.options.hierarchical.enabled === true) { - // set the physics - if (allOptions.physics === undefined || allOptions.physics === true) { - allOptions.physics = { solver: "hierarchicalRepulsion" }; - } else if (options.physics !== false) { - allOptions.physics.solver = "hierarchicalRepulsion"; - } - - // get the type of static smooth curve in case it is required - var type = "horizontal"; - if (this.options.hierarchical.direction === "RL" || this.options.hierarchical.direction === "LR") { - type = "vertical"; - } - // disable smooth curves if nothing is defined. If smooth curves have been turned on, turn them into static smooth curves. - if (allOptions.edges === undefined) { - allOptions.edges = { smooth: false }; - } else if (allOptions.edges.smooth === undefined) { - allOptions.edges.smooth = false; + if (this.options.hierarchical.enabled === true) { + // make sure the level seperation is the right way up + if (this.options.hierarchical.direction === "RL" || this.options.hierarchical.direction === "DU") { + if (this.options.hierarchical.levelSeparation > 0) { + this.options.hierarchical.levelSeparation *= -1; + } } else { - allOptions.edges.smooth = { enabled: true, dynamic: false, type: type }; + if (this.options.hierarchical.levelSeparation < 0) { + this.options.hierarchical.levelSeparation *= -1; + } } - // force all edges into static smooth curves. - this.body.emitter.emit("_forceDisableDynamicCurves", type); + // because the hierarchical system needs it's own physics and smooth curve settings, we adapt the other options if needed. + return this.adaptAllOptions(allOptions); } - return allOptions; - }, - writable: true, - configurable: true - }, - seededRandom: { - value: function seededRandom() { - var x = Math.sin(this.randomSeed++) * 10000; - return x - Math.floor(x); - }, - writable: true, - configurable: true - }, - positionInitially: { - value: function positionInitially(nodesArray) { - if (this.options.hierarchical.enabled !== true) { - for (var i = 0; i < nodesArray.length; i++) { - var node = nodesArray[i]; - if (!node.isFixed() && (node.x === undefined || node.y === undefined)) { - var radius = 10 * 0.1 * nodesArray.length + 10; - var angle = 2 * Math.PI * this.seededRandom(); - - if (node.options.fixed.x === false) { - node.x = radius * Math.cos(angle); - } - if (node.options.fixed.x === false) { - node.y = radius * Math.sin(angle); - } - } - } + } + return allOptions; + } + }, { + key: "adaptAllOptions", + value: function adaptAllOptions(allOptions) { + if (this.options.hierarchical.enabled === true) { + // set the physics + if (allOptions.physics === undefined || allOptions.physics === true) { + allOptions.physics = { solver: "hierarchicalRepulsion" }; + } else if (options.physics !== false) { + allOptions.physics.solver = "hierarchicalRepulsion"; + } + + // get the type of static smooth curve in case it is required + var type = "horizontal"; + if (this.options.hierarchical.direction === "RL" || this.options.hierarchical.direction === "LR") { + type = "vertical"; + } + + // disable smooth curves if nothing is defined. If smooth curves have been turned on, turn them into static smooth curves. + if (allOptions.edges === undefined) { + allOptions.edges = { smooth: false }; + } else if (allOptions.edges.smooth === undefined) { + allOptions.edges.smooth = false; + } else { + allOptions.edges.smooth = { enabled: true, dynamic: false, type: type }; } - }, - writable: true, - configurable: true - }, - getSeed: { - value: function getSeed() { - return this.initialRandomSeed; - }, - writable: true, - configurable: true - }, - setupHierarchicalLayout: { - - /** - * This is the main function to layout the nodes in a hierarchical way. - * It checks if the node details are supplied correctly - * - * @private - */ - value: function setupHierarchicalLayout() { - if (this.options.hierarchical.enabled === true && this.body.nodeIndices.length > 0) { - // get the size of the largest hubs and check if the user has defined a level for a node. - var node = undefined, - nodeId = undefined; - var definedLevel = false; - var undefinedLevel = false; - this.hierarchicalLevels = {}; - this.nodeSpacing = 100; - - for (nodeId in this.body.nodes) { - if (this.body.nodes.hasOwnProperty(nodeId)) { - node = this.body.nodes[nodeId]; - if (node.options.level !== undefined) { - definedLevel = true; - this.hierarchicalLevels[nodeId] = node.options.level; - } else { - undefinedLevel = 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."); - return; - } 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.options.hierarchical.sortMethod === "hubsize") { - this._determineLevelsByHubsize(); - } else if (this.options.hierarchical.sortMethod === "directed" || "direction") { - this._determineLevelsDirected(); - } + // force all edges into static smooth curves. + this.body.emitter.emit("_forceDisableDynamicCurves", type); + } + return allOptions; + } + }, { + key: "seededRandom", + value: function seededRandom() { + var x = Math.sin(this.randomSeed++) * 10000; + return x - Math.floor(x); + } + }, { + key: "positionInitially", + value: function positionInitially(nodesArray) { + if (this.options.hierarchical.enabled !== true) { + for (var i = 0; i < nodesArray.length; i++) { + var node = nodesArray[i]; + if (!node.isFixed() && (node.x === undefined || node.y === undefined)) { + var radius = 10 * 0.1 * nodesArray.length + 10; + var angle = 2 * Math.PI * this.seededRandom(); + + if (node.options.fixed.x === false) { + node.x = radius * Math.cos(angle); } - // check the distribution of the nodes per level. - var distribution = this._getDistribution(); - - // place the nodes on the canvas. - this._placeNodesByHierarchy(distribution); - } - } - }, - writable: true, - configurable: true - }, - _placeNodesByHierarchy: { - - /** - * This function places the nodes on the canvas based on the hierarchial distribution. - * - * @param {Object} distribution | obtained by the function this._getDistribution() - * @private - */ - value: function _placeNodesByHierarchy(distribution) { - var nodeId = undefined, - node = undefined; - this.positionedNodes = {}; - - // 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.options.hierarchical.direction === "UD" || this.options.hierarchical.direction === "DU") { - if (node.x === undefined) { - node.x = distribution[level].distance; - } - distribution[level].distance = node.x + this.nodeSpacing; - } else { - if (node.y === undefined) { - node.y = distribution[level].distance; - } - distribution[level].distance = node.y + this.nodeSpacing; - } - - this.positionedNodes[nodeId] = true; - this._placeBranchNodes(node.edges, node.id, distribution, level); - } + if (node.options.fixed.x === false) { + node.y = radius * Math.sin(angle); } } } - }, - writable: true, - configurable: true - }, - _getDistribution: { - + } + } + }, { + key: "getSeed", + value: function getSeed() { + return this.initialRandomSeed; + } + }, { + key: "setupHierarchicalLayout", - /** - * This function get the distribution of levels based on hubsize - * - * @returns {Object} - * @private - */ - value: function _getDistribution() { - var distribution = {}; - var nodeId = undefined, - node = undefined; + /** + * This is the main function to layout the nodes in a hierarchical way. + * It checks if the node details are supplied correctly + * + * @private + */ + value: function setupHierarchicalLayout() { + if (this.options.hierarchical.enabled === true && this.body.nodeIndices.length > 0) { + // get the size of the largest hubs and check if the user has defined a level for a node. + var node = undefined, + nodeId = undefined; + var definedLevel = false; + var undefinedLevel = false; + this.hierarchicalLevels = {}; + this.nodeSpacing = 100; - // 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.body.nodes) { if (this.body.nodes.hasOwnProperty(nodeId)) { node = this.body.nodes[nodeId]; - if (this.options.hierarchical.direction === "UD" || this.options.hierarchical.direction === "DU") { - node.y = this.options.hierarchical.levelSeparation * this.hierarchicalLevels[nodeId]; - node.options.fixed.y = true; + if (node.options.level !== undefined) { + definedLevel = true; + this.hierarchicalLevels[nodeId] = node.options.level; } else { - node.x = this.options.hierarchical.levelSeparation * this.hierarchicalLevels[nodeId]; - node.options.fixed.x = true; - } - if (distribution[this.hierarchicalLevels[nodeId]] === undefined) { - distribution[this.hierarchicalLevels[nodeId]] = { amount: 0, nodes: {}, distance: 0 }; + undefinedLevel = true; } - distribution[this.hierarchicalLevels[nodeId]].amount += 1; - distribution[this.hierarchicalLevels[nodeId]].nodes[nodeId] = node; } } - return distribution; - }, - writable: true, - configurable: true - }, - _getHubSize: { - - /** - * Get the hubsize from all remaining unlevelled nodes. - * - * @returns {number} - * @private - */ - value: function _getHubSize() { - var hubSize = 0; - for (var nodeId in this.body.nodes) { - if (this.body.nodes.hasOwnProperty(nodeId)) { - var node = this.body.nodes[nodeId]; - if (this.hierarchicalLevels[nodeId] === undefined) { - hubSize = node.edges.length < hubSize ? 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."); + return; + } 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.options.hierarchical.sortMethod === "hubsize") { + this._determineLevelsByHubsize(); + } else if (this.options.hierarchical.sortMethod === "directed" || "direction") { + this._determineLevelsDirected(); } } - } - return hubSize; - }, - writable: true, - configurable: true - }, - _determineLevelsByHubsize: { - + // check the distribution of the nodes per level. + var distribution = this._getDistribution(); - /** - * this function allocates nodes in levels based on the recursive branching from the largest hubs. - * - * @param hubsize - * @private - */ - value: function _determineLevelsByHubsize() { - var nodeId = undefined, - node = undefined; - var hubSize = 1; - - while (hubSize > 0) { - // determine hubs - hubSize = this._getHubSize(); - if (hubSize === 0) break; + // place the nodes on the canvas. + this._placeNodesByHierarchy(distribution); + } + } + } + }, { + key: "_placeNodesByHierarchy", - for (nodeId in this.body.nodes) { - if (this.body.nodes.hasOwnProperty(nodeId)) { - node = this.body.nodes[nodeId]; - if (node.edges.length === hubSize) { - this._setLevel(0, node); + /** + * This function places the nodes on the canvas based on the hierarchial distribution. + * + * @param {Object} distribution | obtained by the function this._getDistribution() + * @private + */ + value: function _placeNodesByHierarchy(distribution) { + var nodeId = undefined, + node = undefined; + this.positionedNodes = {}; + + // 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.options.hierarchical.direction === "UD" || this.options.hierarchical.direction === "DU") { + if (node.x === undefined) { + node.x = distribution[level].distance; + } + distribution[level].distance = node.x + this.nodeSpacing; + } else { + if (node.y === undefined) { + node.y = distribution[level].distance; + } + distribution[level].distance = node.y + this.nodeSpacing; } + + this.positionedNodes[nodeId] = true; + this._placeBranchNodes(node.edges, node.id, distribution, level); } } } - }, - writable: true, - configurable: true - }, - _setLevel: { - + } + } + }, { + key: "_getDistribution", - /** - * 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 - */ - value: function _setLevel(level, node) { - if (this.hierarchicalLevels[node.id] !== undefined) { - return; - }var childNode = undefined; - this.hierarchicalLevels[node.id] = level; - for (var i = 0; i < node.edges.length; i++) { - if (node.edges[i].toId === node.id) { - childNode = node.edges[i].from; + /** + * This function get the distribution of levels based on hubsize + * + * @returns {Object} + * @private + */ + value: function _getDistribution() { + var distribution = {}; + var nodeId = undefined, + node = undefined; + + // 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.body.nodes) { + if (this.body.nodes.hasOwnProperty(nodeId)) { + node = this.body.nodes[nodeId]; + if (this.options.hierarchical.direction === "UD" || this.options.hierarchical.direction === "DU") { + node.y = this.options.hierarchical.levelSeparation * this.hierarchicalLevels[nodeId]; + node.options.fixed.y = true; } else { - childNode = node.edges[i].to; + node.x = this.options.hierarchical.levelSeparation * this.hierarchicalLevels[nodeId]; + node.options.fixed.x = true; } - this._setLevel(level + 1, childNode); + if (distribution[this.hierarchicalLevels[nodeId]] === undefined) { + distribution[this.hierarchicalLevels[nodeId]] = { amount: 0, nodes: {}, distance: 0 }; + } + distribution[this.hierarchicalLevels[nodeId]].amount += 1; + distribution[this.hierarchicalLevels[nodeId]].nodes[nodeId] = node; } - }, - writable: true, - configurable: true - }, - _determineLevelsDirected: { + } + return distribution; + } + }, { + key: "_getHubSize", + /** + * Get the hubsize from all remaining unlevelled nodes. + * + * @returns {number} + * @private + */ + value: function _getHubSize() { + var hubSize = 0; + for (var nodeId in this.body.nodes) { + if (this.body.nodes.hasOwnProperty(nodeId)) { + var node = this.body.nodes[nodeId]; + if (this.hierarchicalLevels[nodeId] === undefined) { + hubSize = node.edges.length < hubSize ? hubSize : node.edges.length; + } + } + } + return hubSize; + } + }, { + key: "_determineLevelsByHubsize", + /** + * this function allocates nodes in levels based on the recursive branching from the largest hubs. + * + * @param hubsize + * @private + */ + value: function _determineLevelsByHubsize() { + var nodeId = undefined, + node = undefined; + var hubSize = 1; - /** - * this function allocates nodes in levels based on the direction of the edges - * - * @param hubsize - * @private - */ - value: function _determineLevelsDirected() { - var nodeId = undefined, - node = undefined; - var minLevel = 10000; + while (hubSize > 0) { + // determine hubs + hubSize = this._getHubSize(); + if (hubSize === 0) break; - // set first node to source for (nodeId in this.body.nodes) { if (this.body.nodes.hasOwnProperty(nodeId)) { node = this.body.nodes[nodeId]; - this._setLevelDirected(minLevel, node); + if (node.edges.length === hubSize) { + this._setLevel(0, node); + } } } + } + } + }, { + key: "_setLevel", - // get the minimum level - for (nodeId in this.body.nodes) { - if (this.body.nodes.hasOwnProperty(nodeId)) { - minLevel = this.hierarchicalLevels[nodeId] < minLevel ? this.hierarchicalLevels[nodeId] : minLevel; - } + /** + * 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 + */ + value: function _setLevel(level, node) { + if (this.hierarchicalLevels[node.id] !== undefined) { + return; + }var childNode = undefined; + this.hierarchicalLevels[node.id] = level; + for (var i = 0; i < node.edges.length; i++) { + if (node.edges[i].toId === node.id) { + childNode = node.edges[i].from; + } else { + childNode = node.edges[i].to; } + this._setLevel(level + 1, childNode); + } + } + }, { + key: "_determineLevelsDirected", - // subtract the minimum from the set so we have a range starting from 0 - for (nodeId in this.body.nodes) { - if (this.body.nodes.hasOwnProperty(nodeId)) { - this.hierarchicalLevels[nodeId] -= minLevel; - } - } - }, - writable: true, - configurable: true - }, - _setLevelDirected: { + /** + * this function allocates nodes in levels based on the direction of the edges + * + * @param hubsize + * @private + */ + value: function _determineLevelsDirected() { + var nodeId = undefined, + node = undefined; + var minLevel = 10000; + // set first node to source + for (nodeId in this.body.nodes) { + if (this.body.nodes.hasOwnProperty(nodeId)) { + node = this.body.nodes[nodeId]; + this._setLevelDirected(minLevel, node); + } + } - /** - * 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 - */ - value: function _setLevelDirected(level, node) { - if (this.hierarchicalLevels[node.id] !== undefined) { - return; - }var childNode = undefined; - this.hierarchicalLevels[node.id] = level; + // get the minimum level + for (nodeId in this.body.nodes) { + if (this.body.nodes.hasOwnProperty(nodeId)) { + minLevel = this.hierarchicalLevels[nodeId] < minLevel ? this.hierarchicalLevels[nodeId] : minLevel; + } + } - for (var i = 0; i < node.edges.length; i++) { - if (node.edges[i].toId === node.id) { - childNode = node.edges[i].from; - this._setLevelDirected(level - 1, childNode); - } else { - childNode = node.edges[i].to; - this._setLevelDirected(level + 1, childNode); - } + // subtract the minimum from the set so we have a range starting from 0 + for (nodeId in this.body.nodes) { + if (this.body.nodes.hasOwnProperty(nodeId)) { + this.hierarchicalLevels[nodeId] -= minLevel; } - }, - writable: true, - configurable: true - }, - _placeBranchNodes: { + } + } + }, { + key: "_setLevelDirected", + /** + * this function is called recursively to enumerate the branched of the first node and give each node a level based on edge direction + * + * @param level + * @param edges + * @param parentId + * @private + */ + value: function _setLevelDirected(level, node) { + if (this.hierarchicalLevels[node.id] !== undefined) { + return; + }var childNode = undefined; + this.hierarchicalLevels[node.id] = level; + for (var i = 0; i < node.edges.length; i++) { + if (node.edges[i].toId === node.id) { + childNode = node.edges[i].from; + this._setLevelDirected(level - 1, childNode); + } else { + childNode = node.edges[i].to; + this._setLevelDirected(level + 1, childNode); + } + } + } + }, { + key: "_placeBranchNodes", - /** - * This is a recursively called function to enumerate the branches from the largest hubs and place the nodes - * on a X position that ensures there will be no overlap. - * - * @param edges - * @param parentId - * @param distribution - * @param parentLevel - * @private - */ - value: function _placeBranchNodes(edges, parentId, distribution, parentLevel) { - for (var i = 0; i < edges.length; i++) { - var childNode = undefined; - var parentNode = undefined; - if (edges[i].toId === parentId) { - childNode = edges[i].from; - parentNode = edges[i].to; - } else { - childNode = edges[i].to; - parentNode = edges[i].from; - } - var childNodeLevel = this.hierarchicalLevels[childNode.id]; - if (this.positionedNodes[childNode.id] === undefined) { - // if a node is conneceted to another node on the same level (or higher (means lower level))!, this is not handled here. - if (childNodeLevel > parentLevel) { - if (this.options.hierarchical.direction === "UD" || this.options.hierarchical.direction === "DU") { - if (childNode.x === undefined) { - childNode.x = Math.max(distribution[childNodeLevel].distance, parentNode.x); - } - distribution[childNodeLevel].distance = childNode.x + this.nodeSpacing; - this.positionedNodes[childNode.id] = true; - } else { - if (childNode.y === undefined) { - childNode.y = Math.max(distribution[childNodeLevel].distance, parentNode.y); - } - distribution[childNodeLevel].distance = childNode.y + this.nodeSpacing; + /** + * This is a recursively called function to enumerate the branches from the largest hubs and place the nodes + * on a X position that ensures there will be no overlap. + * + * @param edges + * @param parentId + * @param distribution + * @param parentLevel + * @private + */ + value: function _placeBranchNodes(edges, parentId, distribution, parentLevel) { + for (var i = 0; i < edges.length; i++) { + var childNode = undefined; + var parentNode = undefined; + if (edges[i].toId === parentId) { + childNode = edges[i].from; + parentNode = edges[i].to; + } else { + childNode = edges[i].to; + parentNode = edges[i].from; + } + var childNodeLevel = this.hierarchicalLevels[childNode.id]; + if (this.positionedNodes[childNode.id] === undefined) { + // if a node is conneceted to another node on the same level (or higher (means lower level))!, this is not handled here. + if (childNodeLevel > parentLevel) { + if (this.options.hierarchical.direction === "UD" || this.options.hierarchical.direction === "DU") { + if (childNode.x === undefined) { + childNode.x = Math.max(distribution[childNodeLevel].distance, parentNode.x); } + distribution[childNodeLevel].distance = childNode.x + this.nodeSpacing; this.positionedNodes[childNode.id] = true; - - if (childNode.edges.length > 1) { - this._placeBranchNodes(childNode.edges, childNode.id, distribution, childNodeLevel); + } else { + if (childNode.y === undefined) { + childNode.y = Math.max(distribution[childNodeLevel].distance, parentNode.y); } + distribution[childNodeLevel].distance = childNode.y + this.nodeSpacing; + } + this.positionedNodes[childNode.id] = true; + + if (childNode.edges.length > 1) { + this._placeBranchNodes(childNode.edges, childNode.id, distribution, childNodeLevel); } } } - }, - writable: true, - configurable: true + } } - }); + }]); return LayoutEngine; })(); - module.exports = LayoutEngine; + exports["default"] = LayoutEngine; + module.exports = exports["default"]; /***/ }, -/* 61 */ +/* 60 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + Object.defineProperty(exports, '__esModule', { + value: true + }); var util = __webpack_require__(1); var Hammer = __webpack_require__(41); - var hammerUtil = __webpack_require__(64); - var locales = __webpack_require__(66); + var hammerUtil = __webpack_require__(44); + var locales = __webpack_require__(79); /** * clears the toolbar div element of children * * @private */ + var ManipulationSystem = (function () { function ManipulationSystem(body, canvas, selectionHandler) { _classCallCheck(this, ManipulationSystem); @@ -23120,7 +23412,7 @@ return /******/ (function(modules) { // webpackBootstrap this.defaultOptions = { enabled: false, initiallyVisible: false, - locale: "en", + locale: 'en', locales: locales, functionality: { addNode: true, @@ -23139,9 +23431,9 @@ return /******/ (function(modules) { // webpackBootstrap deleteEdge: undefined }, controlNodeStyle: { - shape: "dot", + shape: 'dot', size: 6, - color: { background: "#ff0000", border: "#3c3c3c", highlight: { background: "#07f968" } }, + color: { background: '#ff0000', border: '#3c3c3c', highlight: { background: '#07f968' } }, borderWidth: 2, borderWidthSelected: 2 } @@ -23149,1129 +23441,1042 @@ return /******/ (function(modules) { // webpackBootstrap util.extend(this.options, this.defaultOptions); } - _prototypeProperties(ManipulationSystem, null, { - setOptions: { + _createClass(ManipulationSystem, [{ + key: 'setOptions', - - /** - * Set the Options - * @param options - */ - value: function setOptions(options) { - if (options !== undefined) { - if (typeof options === "boolean") { - this.options.enabled = options; - } else { - this.options.enabled = true; - util.deepExtend(this.options, options); - } - if (this.options.initiallyVisible === true) { - this.editMode = true; - } - this._setup(); + /** + * Set the Options + * @param options + */ + value: function setOptions(options) { + if (options !== undefined) { + if (typeof options === 'boolean') { + this.options.enabled = options; + } else { + this.options.enabled = true; + util.deepExtend(this.options, options); } - }, - writable: true, - configurable: true - }, - toggleEditMode: { - - - /** - * Enable or disable edit-mode. Draws the DOM required and cleans up after itself. - * - * @private - */ - value: function toggleEditMode() { - this.editMode = !this.editMode; - if (this.guiEnabled === true) { - 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"; - this._bindHammerToDiv(closeDiv, this.toggleEditMode.bind(this)); - this.showManipulatorToolbar(); - } else { - toolbar.style.display = "none"; - closeDiv.style.display = "none"; - editModeDiv.style.display = "block"; - this._createEditButton(); - } + if (this.options.initiallyVisible === true) { + this.editMode = true; } - }, - writable: true, - configurable: true - }, - showManipulatorToolbar: { - - - /** - * Creates the main toolbar. Removes functions bound to the select event. Binds all the buttons of the toolbar. - * - * @private - */ - value: function showManipulatorToolbar() { - // restore the state of any bound functions or events, remove control nodes, restore physics - this._clean(); + this._setup(); + } + } + }, { + key: 'toggleEditMode', - // reset global letiables - this.manipulationDOM = {}; + /** + * Enable or disable edit-mode. Draws the DOM required and cleans up after itself. + * + * @private + */ + value: function toggleEditMode() { + this.editMode = !this.editMode; + if (this.guiEnabled === true) { + 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'; + this._bindHammerToDiv(closeDiv, this.toggleEditMode.bind(this)); + this.showManipulatorToolbar(); + } else { + toolbar.style.display = 'none'; + closeDiv.style.display = 'none'; + editModeDiv.style.display = 'block'; + this._createEditButton(); + } + } + } + }, { + key: 'showManipulatorToolbar', - var selectedNodeCount = this.selectionHandler._getSelectedNodeCount(); - var selectedEdgeCount = this.selectionHandler._getSelectedEdgeCount(); - var selectedTotalCount = selectedNodeCount + selectedEdgeCount; - var locale = this.options.locales[this.options.locale]; - var needSeperator = false; + /** + * Creates the main toolbar. Removes functions bound to the select event. Binds all the buttons of the toolbar. + * + * @private + */ + value: function showManipulatorToolbar() { + // restore the state of any bound functions or events, remove control nodes, restore physics + this._clean(); + + // reset global letiables + this.manipulationDOM = {}; + + var selectedNodeCount = this.selectionHandler._getSelectedNodeCount(); + var selectedEdgeCount = this.selectionHandler._getSelectedEdgeCount(); + var selectedTotalCount = selectedNodeCount + selectedEdgeCount; + var locale = this.options.locales[this.options.locale]; + var needSeperator = false; + + if (this.options.functionality.addNode === true) { + this._createAddNodeButton(locale); + needSeperator = true; + } + if (this.options.functionality.addEdge === true) { + if (needSeperator === true) { + this._createSeperator(1); + } else { + needSeperator = true; + } + this._createAddEdgeButton(locale); + } - if (this.options.functionality.addNode === true) { - this._createAddNodeButton(locale); + if (selectedNodeCount === 1 && typeof this.options.handlerFunctions.editNode === 'function' && this.options.functionality.editNode === true) { + if (needSeperator === true) { + this._createSeperator(2); + } else { needSeperator = true; } - if (this.options.functionality.addEdge === true) { - if (needSeperator === true) { - this._createSeperator(1); - } else { - needSeperator = true; - } - this._createAddEdgeButton(locale); + this._createEditNodeButton(locale); + } else if (selectedEdgeCount === 1 && selectedNodeCount === 0 && this.options.functionality.editEdge === true) { + if (needSeperator === true) { + this._createSeperator(3); + } else { + needSeperator = true; } + this._createEditEdgeButton(locale); + } - if (selectedNodeCount === 1 && typeof this.options.handlerFunctions.editNode === "function" && this.options.functionality.editNode === true) { + // remove buttons + if (selectedTotalCount !== 0) { + if (selectedNodeCount === 1 && this.options.functionality.deleteNode === true) { if (needSeperator === true) { - this._createSeperator(2); - } else { - needSeperator = true; + this._createSeperator(4); } - this._createEditNodeButton(locale); - } else if (selectedEdgeCount === 1 && selectedNodeCount === 0 && this.options.functionality.editEdge === true) { + this._createDeleteButton(locale); + } else if (selectedNodeCount === 0 && this.options.functionality.deleteEdge === true) { if (needSeperator === true) { - this._createSeperator(3); - } else { - needSeperator = true; - } - this._createEditEdgeButton(locale); - } - - // remove buttons - if (selectedTotalCount !== 0) { - if (selectedNodeCount === 1 && this.options.functionality.deleteNode === true) { - if (needSeperator === true) { - this._createSeperator(4); - } - this._createDeleteButton(locale); - } else if (selectedNodeCount === 0 && this.options.functionality.deleteEdge === true) { - if (needSeperator === true) { - this._createSeperator(4); - } - this._createDeleteButton(locale); + this._createSeperator(4); } + this._createDeleteButton(locale); } + } - // bind the close button - this._bindHammerToDiv(this.closeDiv, this.toggleEditMode.bind(this)); - - // refresh this bar based on what has been selected - this._temporaryBindEvent("select", this.showManipulatorToolbar.bind(this)); + // bind the close button + this._bindHammerToDiv(this.closeDiv, this.toggleEditMode.bind(this)); - // redraw to show any possible changes - this.body.emitter.emit("_redraw"); - }, - writable: true, - configurable: true - }, - addNodeMode: { + // refresh this bar based on what has been selected + this._temporaryBindEvent('select', this.showManipulatorToolbar.bind(this)); + // redraw to show any possible changes + this.body.emitter.emit('_redraw'); + } + }, { + key: 'addNodeMode', - /** - * Create the toolbar for adding Nodes - * - * @private - */ - value: function addNodeMode() { - // clear the toolbar - this._clean(); + /** + * Create the toolbar for adding Nodes + * + * @private + */ + value: function addNodeMode() { + // clear the toolbar + this._clean(); - if (this.guiEnabled === true) { - var locale = this.options.locales[this.options.locale]; - this.manipulationDOM = {}; - this._createBackButton(locale); - this._createSeperator(); - this._createDescription(locale.addDescription); + if (this.guiEnabled === true) { + var locale = this.options.locales[this.options.locale]; + this.manipulationDOM = {}; + this._createBackButton(locale); + this._createSeperator(); + this._createDescription(locale.addDescription); - // bind the close button - this._bindHammerToDiv(this.closeDiv, this.toggleEditMode.bind(this)); - } + // bind the close button + this._bindHammerToDiv(this.closeDiv, this.toggleEditMode.bind(this)); + } - this._temporaryBindEvent("click", this._performAddNode.bind(this)); - }, - writable: true, - configurable: true - }, - editNode: { + this._temporaryBindEvent('click', this._performAddNode.bind(this)); + } + }, { + key: 'editNode', - /** - * call the bound function to handle the editing of the node. The node has to be selected. - * - * @private - */ - value: function editNode() { - var _this = this; - if (typeof this.options.handlerFunctions.editNode === "function") { - var node = this.selectionHandler._getSelectedNode(); - if (node.isCluster !== true) { - var data = util.deepExtend({}, node.options, true); - data.x = node.x; - data.y = node.y; - - if (this.options.handlerFunctions.editNode.length === 2) { - this.options.handlerFunctions.editNode(data, function (finalizedData) { - _this.body.data.nodes.update(finalizedData); - _this.showManipulatorToolbar(); - }); - } else { - throw new Error("The function for edit does not support two arguments (data, callback)"); - } + /** + * call the bound function to handle the editing of the node. The node has to be selected. + * + * @private + */ + value: function editNode() { + var _this = this; + + if (typeof this.options.handlerFunctions.editNode === 'function') { + var node = this.selectionHandler._getSelectedNode(); + if (node.isCluster !== true) { + var data = util.deepExtend({}, node.options, true); + data.x = node.x; + data.y = node.y; + + if (this.options.handlerFunctions.editNode.length === 2) { + this.options.handlerFunctions.editNode(data, function (finalizedData) { + _this.body.data.nodes.update(finalizedData); + _this.showManipulatorToolbar(); + }); } else { - alert(this.options.locales[this.options.locale].editClusterError); + throw new Error('The function for edit does not support two arguments (data, callback)'); } } else { - throw new Error("No function has been configured to handle the editing of nodes."); + alert(this.options.locales[this.options.locale].editClusterError); } - }, - writable: true, - configurable: true - }, - addEdgeMode: { - + } else { + throw new Error('No function has been configured to handle the editing of nodes.'); + } + } + }, { + key: 'addEdgeMode', - /** - * create the toolbar to connect nodes - * - * @private - */ - value: function addEdgeMode() { - // _clean the system - this._clean(); + /** + * create the toolbar to connect nodes + * + * @private + */ + value: function addEdgeMode() { + // _clean the system + this._clean(); - if (this.guiEnabled === true) { - var locale = this.options.locales[this.options.locale]; - this.manipulationDOM = {}; - this._createBackButton(locale); - this._createSeperator(); - this._createDescription(locale.edgeDescription); + if (this.guiEnabled === true) { + var locale = this.options.locales[this.options.locale]; + this.manipulationDOM = {}; + this._createBackButton(locale); + this._createSeperator(); + this._createDescription(locale.edgeDescription); - // bind the close button - this._bindHammerToDiv(this.closeDiv, this.toggleEditMode.bind(this)); - } + // bind the close button + this._bindHammerToDiv(this.closeDiv, this.toggleEditMode.bind(this)); + } - // temporarily overload functions - this._temporaryBindUI("onTouch", this._handleConnect.bind(this)); - this._temporaryBindUI("onDragEnd", this._finishConnect.bind(this)); - this._temporaryBindUI("onHold", function () {}); - }, - writable: true, - configurable: true - }, - editEdgeMode: { + // temporarily overload functions + this._temporaryBindUI('onTouch', this._handleConnect.bind(this)); + this._temporaryBindUI('onDragEnd', this._finishConnect.bind(this)); + this._temporaryBindUI('onHold', function () {}); + } + }, { + key: 'editEdgeMode', - /** - * create the toolbar to edit edges - * - * @private - */ - value: function editEdgeMode() { - // clear the system - this._clean(); - - if (this.guiEnabled === true) { - var locale = this.options.locales[this.options.locale]; - this.manipulationDOM = {}; - this._createBackButton(locale); - this._createSeperator(); - this._createDescription(locale.editEdgeDescription); - - // bind the close button - this._bindHammerToDiv(this.closeDiv, this.toggleEditMode.bind(this)); - } - - this.edgeBeingEditedId = this.selectionHandler.getSelectedEdges()[0]; - var edge = this.body.edges[this.edgeBeingEditedId]; - - // create control nodes - var controlNodeFrom = this._getNewTargetNode(edge.from.x, edge.from.y); - var controlNodeTo = this._getNewTargetNode(edge.to.x, edge.to.y); - - this.temporaryIds.nodes.push(controlNodeFrom.id); - this.temporaryIds.nodes.push(controlNodeTo.id); - - this.body.nodes[controlNodeFrom.id] = controlNodeFrom; - this.body.nodeIndices.push(controlNodeFrom.id); - this.body.nodes[controlNodeTo.id] = controlNodeTo; - this.body.nodeIndices.push(controlNodeTo.id); - - // temporarily overload UI functions, cleaned up automatically because of _temporaryBindUI - this._temporaryBindUI("onTouch", this._controlNodeTouch.bind(this)); // used to get the position - this._temporaryBindUI("onTap", function () {}); // disabled - this._temporaryBindUI("onHold", function () {}); // disabled - this._temporaryBindUI("onDragStart", this._controlNodeDragStart.bind(this)); // used to select control node - this._temporaryBindUI("onDrag", this._controlNodeDrag.bind(this)); // used to drag control node - this._temporaryBindUI("onDragEnd", this._controlNodeDragEnd.bind(this)); // used to connect or revert control nodes - this._temporaryBindUI("onMouseMove", function () {}); // disabled - - // create function to position control nodes correctly on movement - // automatically cleaned up because we use the temporary bind - this._temporaryBindEvent("beforeDrawing", function (ctx) { - var positions = edge.edgeType.findBorderPositions(ctx); - if (controlNodeFrom.selected === false) { - controlNodeFrom.x = positions.from.x; - controlNodeFrom.y = positions.from.y; - } - if (controlNodeTo.selected === false) { - controlNodeTo.x = positions.to.x; - controlNodeTo.y = positions.to.y; - } - }); + /** + * create the toolbar to edit edges + * + * @private + */ + value: function editEdgeMode() { + // clear the system + this._clean(); - this.body.emitter.emit("_redraw"); - }, - writable: true, - configurable: true - }, - deleteSelected: { + if (this.guiEnabled === true) { + var locale = this.options.locales[this.options.locale]; + this.manipulationDOM = {}; + this._createBackButton(locale); + this._createSeperator(); + this._createDescription(locale.editEdgeDescription); - /** - * delete everything in the selection - * - * @private - */ - value: function deleteSelected() { - var _this = this; - var selectedNodes = this.selectionHandler.getSelectedNodes(); - var selectedEdges = this.selectionHandler.getSelectedEdges(); - var deleteFunction = undefined; - if (selectedNodes.length > 0) { - for (var i = 0; i < selectedNodes.length; i++) { - if (this.body.nodes[selectedNodes[i]].isCluster === true) { - alert(this.options.locales[this.options.locale].deleteClusterError); - return; - } - } + // bind the close button + this._bindHammerToDiv(this.closeDiv, this.toggleEditMode.bind(this)); + } - if (typeof this.options.handlerFunctions.deleteNode === "function") { - deleteFunction = this.options.handlerFunctions.deleteNode; - } - } else if (selectedEdges.length > 0) { - if (typeof this.options.handlerFunctions.deleteEdge === "function") { - deleteFunction = this.options.handlerFunctions.deleteEdge; - } + this.edgeBeingEditedId = this.selectionHandler.getSelectedEdges()[0]; + var edge = this.body.edges[this.edgeBeingEditedId]; + + // create control nodes + var controlNodeFrom = this._getNewTargetNode(edge.from.x, edge.from.y); + var controlNodeTo = this._getNewTargetNode(edge.to.x, edge.to.y); + + this.temporaryIds.nodes.push(controlNodeFrom.id); + this.temporaryIds.nodes.push(controlNodeTo.id); + + this.body.nodes[controlNodeFrom.id] = controlNodeFrom; + this.body.nodeIndices.push(controlNodeFrom.id); + this.body.nodes[controlNodeTo.id] = controlNodeTo; + this.body.nodeIndices.push(controlNodeTo.id); + + // temporarily overload UI functions, cleaned up automatically because of _temporaryBindUI + this._temporaryBindUI('onTouch', this._controlNodeTouch.bind(this)); // used to get the position + this._temporaryBindUI('onTap', function () {}); // disabled + this._temporaryBindUI('onHold', function () {}); // disabled + this._temporaryBindUI('onDragStart', this._controlNodeDragStart.bind(this)); // used to select control node + this._temporaryBindUI('onDrag', this._controlNodeDrag.bind(this)); // used to drag control node + this._temporaryBindUI('onDragEnd', this._controlNodeDragEnd.bind(this)); // used to connect or revert control nodes + this._temporaryBindUI('onMouseMove', function () {}); // disabled + + // create function to position control nodes correctly on movement + // automatically cleaned up because we use the temporary bind + this._temporaryBindEvent('beforeDrawing', function (ctx) { + var positions = edge.edgeType.findBorderPositions(ctx); + if (controlNodeFrom.selected === false) { + controlNodeFrom.x = positions.from.x; + controlNodeFrom.y = positions.from.y; + } + if (controlNodeTo.selected === false) { + controlNodeTo.x = positions.to.x; + controlNodeTo.y = positions.to.y; } + }); - if (typeof deleteFunction === "function") { - var data = { nodes: selectedNodes, edges: selectedEdges }; - if (deleteFunction.length === 2) { - deleteFunction(data, function (finalizedData) { - _this.body.data.edges.remove(finalizedData.edges); - _this.body.data.nodes.remove(finalizedData.nodes); - _this.body.emitter.emit("startSimulation"); - }); - } else { - throw new Error("The function for delete does not support two arguments (data, callback)"); + this.body.emitter.emit('_redraw'); + } + }, { + key: 'deleteSelected', + + /** + * delete everything in the selection + * + * @private + */ + value: function deleteSelected() { + var _this2 = this; + + var selectedNodes = this.selectionHandler.getSelectedNodes(); + var selectedEdges = this.selectionHandler.getSelectedEdges(); + var deleteFunction = undefined; + if (selectedNodes.length > 0) { + for (var i = 0; i < selectedNodes.length; i++) { + if (this.body.nodes[selectedNodes[i]].isCluster === true) { + alert(this.options.locales[this.options.locale].deleteClusterError); + return; } - } else { - this.body.data.edges.remove(selectedEdges); - this.body.data.nodes.remove(selectedNodes); - this.body.emitter.emit("startSimulation"); } - }, - writable: true, - configurable: true - }, - _setup: { - + if (typeof this.options.handlerFunctions.deleteNode === 'function') { + deleteFunction = this.options.handlerFunctions.deleteNode; + } + } else if (selectedEdges.length > 0) { + if (typeof this.options.handlerFunctions.deleteEdge === 'function') { + deleteFunction = this.options.handlerFunctions.deleteEdge; + } + } + if (typeof deleteFunction === 'function') { + var data = { nodes: selectedNodes, edges: selectedEdges }; + if (deleteFunction.length === 2) { + deleteFunction(data, function (finalizedData) { + _this2.body.data.edges.remove(finalizedData.edges); + _this2.body.data.nodes.remove(finalizedData.nodes); + _this2.body.emitter.emit('startSimulation'); + }); + } else { + throw new Error('The function for delete does not support two arguments (data, callback)'); + } + } else { + this.body.data.edges.remove(selectedEdges); + this.body.data.nodes.remove(selectedNodes); + this.body.emitter.emit('startSimulation'); + } + } + }, { + key: '_setup', - //********************************************** PRIVATE ***************************************// + //********************************************** PRIVATE ***************************************// - /** - * draw or remove the DOM - * @private - */ - value: function _setup() { - if (this.options.enabled === true) { - // Enable the GUI - this.guiEnabled = true; + /** + * draw or remove the DOM + * @private + */ + value: function _setup() { + if (this.options.enabled === true) { + // Enable the GUI + this.guiEnabled = true; - // remove override - this.selectionHandler.forceSelectEdges = true; + // remove override + this.selectionHandler.forceSelectEdges = true; - this._createWrappers(); - if (this.editMode === false) { - this._createEditButton(); - } else { - this.showManipulatorToolbar(); - } + this._createWrappers(); + if (this.editMode === false) { + this._createEditButton(); } else { - this._removeManipulationDOM(); - - // disable the gui - this.guiEnabled = false; + this.showManipulatorToolbar(); } - }, - writable: true, - configurable: true - }, - _createWrappers: { + } else { + this._removeManipulationDOM(); + // disable the gui + this.guiEnabled = false; + } + } + }, { + key: '_createWrappers', - /** - * create the div overlays that contain the DOM - * @private - */ - value: function _createWrappers() { - // 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.canvas.frame.appendChild(this.manipulationDiv); + /** + * create the div overlays that contain the DOM + * @private + */ + value: function _createWrappers() { + // 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.canvas.frame.appendChild(this.manipulationDiv); + } - // container for the edit button. - 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.canvas.frame.appendChild(this.editModeDiv); + // container for the edit button. + 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.canvas.frame.appendChild(this.editModeDiv); + } + // container for the close div button + if (this.closeDiv === undefined) { + this.closeDiv = document.createElement('div'); + this.closeDiv.className = 'network-manipulation-closeDiv'; + this.closeDiv.style.display = this.manipulationDiv.style.display; + this.canvas.frame.appendChild(this.closeDiv); + } + } + }, { + key: '_getNewTargetNode', - // container for the close div button - if (this.closeDiv === undefined) { - this.closeDiv = document.createElement("div"); - this.closeDiv.className = "network-manipulation-closeDiv"; - this.closeDiv.style.display = this.manipulationDiv.style.display; - this.canvas.frame.appendChild(this.closeDiv); - } - }, - writable: true, - configurable: true - }, - _getNewTargetNode: { + /** + * generate a new target node. Used for creating new edges and editing edges + * @param x + * @param y + * @returns {*} + * @private + */ + value: function _getNewTargetNode(x, y) { + var controlNodeStyle = util.deepExtend({}, this.options.controlNodeStyle); + controlNodeStyle.id = 'targetNode' + util.randomUUID(); + controlNodeStyle.hidden = false; + controlNodeStyle.physics = false; + controlNodeStyle.x = x; + controlNodeStyle.y = y; - /** - * generate a new target node. Used for creating new edges and editing edges - * @param x - * @param y - * @returns {*} - * @private - */ - value: function _getNewTargetNode(x, y) { - var controlNodeStyle = util.deepExtend({}, this.options.controlNodeStyle); + return this.body.functions.createNode(controlNodeStyle); + } + }, { + key: '_createEditButton', - controlNodeStyle.id = "targetNode" + util.randomUUID(); - controlNodeStyle.hidden = false; - controlNodeStyle.physics = false; - controlNodeStyle.x = x; - controlNodeStyle.y = y; + /** + * Create the edit button + */ + value: function _createEditButton() { + // restore everything to it's original state (if applicable) + this._clean(); - return this.body.functions.createNode(controlNodeStyle); - }, - writable: true, - configurable: true - }, - _createEditButton: { + // reset the manipulationDOM + this.manipulationDOM = {}; + // empty the editModeDiv + util.recursiveDOMDelete(this.editModeDiv); - /** - * Create the edit button - */ - value: function _createEditButton() { - // restore everything to it's original state (if applicable) - this._clean(); + // create the contents for the editMode button + var locale = this.options.locales[this.options.locale]; + var button = this._createButton('editMode', 'network-manipulationUI edit editmode', locale.edit); + this.editModeDiv.appendChild(button); - // reset the manipulationDOM - this.manipulationDOM = {}; + // bind a hammer listener to the button, calling the function toggleEditMode. + this._bindHammerToDiv(button, this.toggleEditMode.bind(this)); + } + }, { + key: '_clean', - // empty the editModeDiv + /** + * this function cleans up after everything this module does. Temporary elements, functions and events are removed, physics restored, hammers removed. + * @private + */ + value: function _clean() { + // _clean the divs + if (this.guiEnabled === true) { util.recursiveDOMDelete(this.editModeDiv); + util.recursiveDOMDelete(this.manipulationDiv); - // create the contents for the editMode button - var locale = this.options.locales[this.options.locale]; - var button = this._createButton("editMode", "network-manipulationUI edit editmode", locale.edit); - this.editModeDiv.appendChild(button); - - // bind a hammer listener to the button, calling the function toggleEditMode. - this._bindHammerToDiv(button, this.toggleEditMode.bind(this)); - }, - writable: true, - configurable: true - }, - _clean: { - - - /** - * this function cleans up after everything this module does. Temporary elements, functions and events are removed, physics restored, hammers removed. - * @private - */ - value: function _clean() { - // _clean the divs - if (this.guiEnabled === true) { - util.recursiveDOMDelete(this.editModeDiv); - util.recursiveDOMDelete(this.manipulationDiv); - - // removes all the bindings and overloads - this._cleanManipulatorHammers(); - } - - // remove temporary nodes and edges - this._cleanupTemporaryNodesAndEdges(); + // removes all the bindings and overloads + this._cleanManipulatorHammers(); + } - // restore overloaded UI functions - this._unbindTemporaryUIs(); + // remove temporary nodes and edges + this._cleanupTemporaryNodesAndEdges(); - // remove the temporaryEventFunctions - this._unbindTemporaryEvents(); + // restore overloaded UI functions + this._unbindTemporaryUIs(); - // restore the physics if required - this.body.emitter.emit("restorePhysics"); - }, - writable: true, - configurable: true - }, - _cleanManipulatorHammers: { + // remove the temporaryEventFunctions + this._unbindTemporaryEvents(); + // restore the physics if required + this.body.emitter.emit('restorePhysics'); + } + }, { + key: '_cleanManipulatorHammers', - /** - * Each dom element has it's own hammer. They are stored in this.manipulationHammers. This cleans them up. - * @private - */ - value: function _cleanManipulatorHammers() { - // _clean hammer bindings - if (this.manipulationHammers.length != 0) { - for (var i = 0; i < this.manipulationHammers.length; i++) { - this.manipulationHammers[i].destroy(); - } - this.manipulationHammers = []; + /** + * Each dom element has it's own hammer. They are stored in this.manipulationHammers. This cleans them up. + * @private + */ + value: function _cleanManipulatorHammers() { + // _clean hammer bindings + if (this.manipulationHammers.length != 0) { + for (var i = 0; i < this.manipulationHammers.length; i++) { + this.manipulationHammers[i].destroy(); } - }, - writable: true, - configurable: true - }, - _removeManipulationDOM: { - - - /** - * Remove all DOM elements created by this module. - * @private - */ - value: function _removeManipulationDOM() { - // removes all the bindings and overloads - this._clean(); - - // empty the manipulation divs - util.recursiveDOMDelete(this.manipulationDiv); - util.recursiveDOMDelete(this.editModeDiv); - util.recursiveDOMDelete(this.closeDiv); - - // remove the manipulation divs - this.canvas.frame.removeChild(this.manipulationDiv); - this.canvas.frame.removeChild(this.editModeDiv); - this.canvas.frame.removeChild(this.closeDiv); - - // set the references to undefined - this.manipulationDiv = undefined; - this.editModeDiv = undefined; - this.closeDiv = undefined; - - // remove override - this.selectionHandler.forceSelectEdges = false; - }, - writable: true, - configurable: true - }, - _createSeperator: { + this.manipulationHammers = []; + } + } + }, { + key: '_removeManipulationDOM', + /** + * Remove all DOM elements created by this module. + * @private + */ + value: function _removeManipulationDOM() { + // removes all the bindings and overloads + this._clean(); - /** - * create a seperator line. the index is to differentiate in the manipulation dom - * @param index - * @private - */ - value: function _createSeperator() { - var index = arguments[0] === undefined ? 1 : arguments[0]; - this.manipulationDOM["seperatorLineDiv" + index] = document.createElement("div"); - this.manipulationDOM["seperatorLineDiv" + index].className = "network-seperatorLine"; - this.manipulationDiv.appendChild(this.manipulationDOM["seperatorLineDiv" + index]); - }, - writable: true, - configurable: true - }, - _createAddNodeButton: { + // empty the manipulation divs + util.recursiveDOMDelete(this.manipulationDiv); + util.recursiveDOMDelete(this.editModeDiv); + util.recursiveDOMDelete(this.closeDiv); - // ---------------------- DOM functions for buttons --------------------------// + // remove the manipulation divs + this.canvas.frame.removeChild(this.manipulationDiv); + this.canvas.frame.removeChild(this.editModeDiv); + this.canvas.frame.removeChild(this.closeDiv); - value: function _createAddNodeButton(locale) { - var button = this._createButton("addNode", "network-manipulationUI add", locale.addNode); - this.manipulationDiv.appendChild(button); - this._bindHammerToDiv(button, this.addNodeMode.bind(this)); - }, - writable: true, - configurable: true - }, - _createAddEdgeButton: { - value: function _createAddEdgeButton(locale) { - var button = this._createButton("addEdge", "network-manipulationUI connect", locale.addEdge); - this.manipulationDiv.appendChild(button); - this._bindHammerToDiv(button, this.addEdgeMode.bind(this)); - }, - writable: true, - configurable: true - }, - _createEditNodeButton: { - value: function _createEditNodeButton(locale) { - var button = this._createButton("editNode", "network-manipulationUI edit", locale.editNode); - this.manipulationDiv.appendChild(button); - this._bindHammerToDiv(button, this.editNode.bind(this)); - }, - writable: true, - configurable: true - }, - _createEditEdgeButton: { - value: function _createEditEdgeButton(locale) { - var button = this._createButton("editEdge", "network-manipulationUI edit", locale.editEdge); - this.manipulationDiv.appendChild(button); - this._bindHammerToDiv(button, this.editEdgeMode.bind(this)); - }, - writable: true, - configurable: true - }, - _createDeleteButton: { - value: function _createDeleteButton(locale) { - var button = this._createButton("delete", "network-manipulationUI delete", locale.del); - this.manipulationDiv.appendChild(button); - this._bindHammerToDiv(button, this.deleteSelected.bind(this)); - }, - writable: true, - configurable: true - }, - _createBackButton: { - value: function _createBackButton(locale) { - var button = this._createButton("back", "network-manipulationUI back", locale.back); - this.manipulationDiv.appendChild(button); - this._bindHammerToDiv(button, this.showManipulatorToolbar.bind(this)); - }, - writable: true, - configurable: true - }, - _createButton: { - value: function _createButton(id, className, label) { - var labelClassName = arguments[3] === undefined ? "network-manipulationLabel" : arguments[3]; - this.manipulationDOM[id + "Div"] = document.createElement("div"); - this.manipulationDOM[id + "Div"].className = className; - this.manipulationDOM[id + "Label"] = document.createElement("div"); - this.manipulationDOM[id + "Label"].className = labelClassName; - this.manipulationDOM[id + "Label"].innerHTML = label; - this.manipulationDOM[id + "Div"].appendChild(this.manipulationDOM[id + "Label"]); - return this.manipulationDOM[id + "Div"]; - }, - writable: true, - configurable: true - }, - _createDescription: { - value: function _createDescription(label) { - this.manipulationDiv.appendChild(this._createButton("description", "network-manipulationUI none", label)); - }, - writable: true, - configurable: true - }, - _temporaryBindEvent: { + // set the references to undefined + this.manipulationDiv = undefined; + this.editModeDiv = undefined; + this.closeDiv = undefined; - // -------------------------- End of DOM functions for buttons ------------------------------// + // remove override + this.selectionHandler.forceSelectEdges = false; + } + }, { + key: '_createSeperator', - /** - * this binds an event until cleanup by the clean functions. - * @param event - * @param newFunction - * @private - */ - value: function _temporaryBindEvent(event, newFunction) { - this.temporaryEventFunctions.push({ event: event, boundFunction: newFunction }); - this.body.emitter.on(event, newFunction); - }, - writable: true, - configurable: true - }, - _temporaryBindUI: { + /** + * create a seperator line. the index is to differentiate in the manipulation dom + * @param index + * @private + */ + value: function _createSeperator() { + var index = arguments[0] === undefined ? 1 : arguments[0]; + + this.manipulationDOM['seperatorLineDiv' + index] = document.createElement('div'); + this.manipulationDOM['seperatorLineDiv' + index].className = 'network-seperatorLine'; + this.manipulationDiv.appendChild(this.manipulationDOM['seperatorLineDiv' + index]); + } + }, { + key: '_createAddNodeButton', + + // ---------------------- DOM functions for buttons --------------------------// + + value: function _createAddNodeButton(locale) { + var button = this._createButton('addNode', 'network-manipulationUI add', locale.addNode); + this.manipulationDiv.appendChild(button); + this._bindHammerToDiv(button, this.addNodeMode.bind(this)); + } + }, { + key: '_createAddEdgeButton', + value: function _createAddEdgeButton(locale) { + var button = this._createButton('addEdge', 'network-manipulationUI connect', locale.addEdge); + this.manipulationDiv.appendChild(button); + this._bindHammerToDiv(button, this.addEdgeMode.bind(this)); + } + }, { + key: '_createEditNodeButton', + value: function _createEditNodeButton(locale) { + var button = this._createButton('editNode', 'network-manipulationUI edit', locale.editNode); + this.manipulationDiv.appendChild(button); + this._bindHammerToDiv(button, this.editNode.bind(this)); + } + }, { + key: '_createEditEdgeButton', + value: function _createEditEdgeButton(locale) { + var button = this._createButton('editEdge', 'network-manipulationUI edit', locale.editEdge); + this.manipulationDiv.appendChild(button); + this._bindHammerToDiv(button, this.editEdgeMode.bind(this)); + } + }, { + key: '_createDeleteButton', + value: function _createDeleteButton(locale) { + var button = this._createButton('delete', 'network-manipulationUI delete', locale.del); + this.manipulationDiv.appendChild(button); + this._bindHammerToDiv(button, this.deleteSelected.bind(this)); + } + }, { + key: '_createBackButton', + value: function _createBackButton(locale) { + var button = this._createButton('back', 'network-manipulationUI back', locale.back); + this.manipulationDiv.appendChild(button); + this._bindHammerToDiv(button, this.showManipulatorToolbar.bind(this)); + } + }, { + key: '_createButton', + value: function _createButton(id, className, label) { + var labelClassName = arguments[3] === undefined ? 'network-manipulationLabel' : arguments[3]; + + this.manipulationDOM[id + 'Div'] = document.createElement('div'); + this.manipulationDOM[id + 'Div'].className = className; + this.manipulationDOM[id + 'Label'] = document.createElement('div'); + this.manipulationDOM[id + 'Label'].className = labelClassName; + this.manipulationDOM[id + 'Label'].innerHTML = label; + this.manipulationDOM[id + 'Div'].appendChild(this.manipulationDOM[id + 'Label']); + return this.manipulationDOM[id + 'Div']; + } + }, { + key: '_createDescription', + value: function _createDescription(label) { + this.manipulationDiv.appendChild(this._createButton('description', 'network-manipulationUI none', label)); + } + }, { + key: '_temporaryBindEvent', + + // -------------------------- End of DOM functions for buttons ------------------------------// - /** - * this overrides an UI function until cleanup by the clean function - * @param UIfunctionName - * @param newFunction - * @private - */ - value: function _temporaryBindUI(UIfunctionName, newFunction) { - if (this.body.eventListeners[UIfunctionName] !== undefined) { - this.temporaryUIFunctions[UIfunctionName] = this.body.eventListeners[UIfunctionName]; - this.body.eventListeners[UIfunctionName] = newFunction; - } else { - throw new Error("This UI function does not exist. Typo? You tried: \"" + UIfunctionName + "\" possible are: " + JSON.stringify(Object.keys(this.body.eventListeners))); - } - }, - writable: true, - configurable: true - }, - _unbindTemporaryUIs: { + /** + * this binds an event until cleanup by the clean functions. + * @param event + * @param newFunction + * @private + */ + value: function _temporaryBindEvent(event, newFunction) { + this.temporaryEventFunctions.push({ event: event, boundFunction: newFunction }); + this.body.emitter.on(event, newFunction); + } + }, { + key: '_temporaryBindUI', - /** - * Restore the overridden UI functions to their original state. - * - * @private - */ - value: function _unbindTemporaryUIs() { - for (var functionName in this.temporaryUIFunctions) { - if (this.temporaryUIFunctions.hasOwnProperty(functionName)) { - this.body.eventListeners[functionName] = this.temporaryUIFunctions[functionName]; - delete this.temporaryUIFunctions[functionName]; - } - } - this.temporaryUIFunctions = {}; - }, - writable: true, - configurable: true - }, - _unbindTemporaryEvents: { + /** + * this overrides an UI function until cleanup by the clean function + * @param UIfunctionName + * @param newFunction + * @private + */ + value: function _temporaryBindUI(UIfunctionName, newFunction) { + if (this.body.eventListeners[UIfunctionName] !== undefined) { + this.temporaryUIFunctions[UIfunctionName] = this.body.eventListeners[UIfunctionName]; + this.body.eventListeners[UIfunctionName] = newFunction; + } else { + throw new Error('This UI function does not exist. Typo? You tried: "' + UIfunctionName + '" possible are: ' + JSON.stringify(Object.keys(this.body.eventListeners))); + } + } + }, { + key: '_unbindTemporaryUIs', - /** - * Unbind the events created by _temporaryBindEvent - * @private - */ - value: function _unbindTemporaryEvents() { - for (var i = 0; i < this.temporaryEventFunctions.length; i++) { - var eventName = this.temporaryEventFunctions[i].event; - var boundFunction = this.temporaryEventFunctions[i].boundFunction; - this.body.emitter.off(eventName, boundFunction); + /** + * Restore the overridden UI functions to their original state. + * + * @private + */ + value: function _unbindTemporaryUIs() { + for (var functionName in this.temporaryUIFunctions) { + if (this.temporaryUIFunctions.hasOwnProperty(functionName)) { + this.body.eventListeners[functionName] = this.temporaryUIFunctions[functionName]; + delete this.temporaryUIFunctions[functionName]; } - this.temporaryEventFunctions = []; - }, - writable: true, - configurable: true - }, - _bindHammerToDiv: { + } + this.temporaryUIFunctions = {}; + } + }, { + key: '_unbindTemporaryEvents', - /** - * Bind an hammer instance to a DOM element. - * @param domElement - * @param funct - */ - value: function _bindHammerToDiv(domElement, boundFunction) { - var hammer = new Hammer(domElement, {}); - hammerUtil.onTouch(hammer, boundFunction); - this.manipulationHammers.push(hammer); - }, - writable: true, - configurable: true - }, - _cleanupTemporaryNodesAndEdges: { + /** + * Unbind the events created by _temporaryBindEvent + * @private + */ + value: function _unbindTemporaryEvents() { + for (var i = 0; i < this.temporaryEventFunctions.length; i++) { + var eventName = this.temporaryEventFunctions[i].event; + var boundFunction = this.temporaryEventFunctions[i].boundFunction; + this.body.emitter.off(eventName, boundFunction); + } + this.temporaryEventFunctions = []; + } + }, { + key: '_bindHammerToDiv', + /** + * Bind an hammer instance to a DOM element. + * @param domElement + * @param funct + */ + value: function _bindHammerToDiv(domElement, boundFunction) { + var hammer = new Hammer(domElement, {}); + hammerUtil.onTouch(hammer, boundFunction); + this.manipulationHammers.push(hammer); + } + }, { + key: '_cleanupTemporaryNodesAndEdges', - /** - * Neatly clean up temporary edges and nodes - * @private - */ - value: function _cleanupTemporaryNodesAndEdges() { - // _clean temporary edges - for (var i = 0; i < this.temporaryIds.edges.length; i++) { - this.body.edges[this.temporaryIds.edges[i]].disconnect(); - delete this.body.edges[this.temporaryIds.edges[i]]; - var indexTempEdge = this.body.edgeIndices.indexOf(this.temporaryIds.edges[i]); - if (indexTempEdge !== -1) { - this.body.edgeIndices.splice(indexTempEdge, 1); - } + /** + * Neatly clean up temporary edges and nodes + * @private + */ + value: function _cleanupTemporaryNodesAndEdges() { + // _clean temporary edges + for (var i = 0; i < this.temporaryIds.edges.length; i++) { + this.body.edges[this.temporaryIds.edges[i]].disconnect(); + delete this.body.edges[this.temporaryIds.edges[i]]; + var indexTempEdge = this.body.edgeIndices.indexOf(this.temporaryIds.edges[i]); + if (indexTempEdge !== -1) { + this.body.edgeIndices.splice(indexTempEdge, 1); } + } - // _clean temporary nodes - for (var i = 0; i < this.temporaryIds.nodes.length; i++) { - delete this.body.nodes[this.temporaryIds.nodes[i]]; - var indexTempNode = this.body.nodeIndices.indexOf(this.temporaryIds.nodes[i]); - if (indexTempNode !== -1) { - this.body.nodeIndices.splice(indexTempNode, 1); - } + // _clean temporary nodes + for (var i = 0; i < this.temporaryIds.nodes.length; i++) { + delete this.body.nodes[this.temporaryIds.nodes[i]]; + var indexTempNode = this.body.nodeIndices.indexOf(this.temporaryIds.nodes[i]); + if (indexTempNode !== -1) { + this.body.nodeIndices.splice(indexTempNode, 1); } + } - this.temporaryIds = { nodes: [], edges: [] }; - }, - writable: true, - configurable: true - }, - _controlNodeTouch: { + this.temporaryIds = { nodes: [], edges: [] }; + } + }, { + key: '_controlNodeTouch', - // ------------------------------------------ EDIT EDGE FUNCTIONS -----------------------------------------// + // ------------------------------------------ EDIT EDGE FUNCTIONS -----------------------------------------// - /** - * the touch is used to get the position of the initial click - * @param event - * @private - */ - value: function _controlNodeTouch(event) { - this.lastTouch = this.body.functions.getPointer(event.center); - this.lastTouch.translation = util.extend({}, this.body.view.translation); // copy the object - }, - writable: true, - configurable: true - }, - _controlNodeDragStart: { + /** + * the touch is used to get the position of the initial click + * @param event + * @private + */ + value: function _controlNodeTouch(event) { + this.lastTouch = this.body.functions.getPointer(event.center); + this.lastTouch.translation = util.extend({}, this.body.view.translation); // copy the object + } + }, { + key: '_controlNodeDragStart', + /** + * the drag start is used to mark one of the control nodes as selected. + * @param event + * @private + */ + value: function _controlNodeDragStart(event) { + var pointer = this.lastTouch; + var pointerObj = this.selectionHandler._pointerToPositionObject(pointer); + var from = this.body.nodes[this.temporaryIds.nodes[0]]; + var to = this.body.nodes[this.temporaryIds.nodes[1]]; + var edge = this.body.edges[this.edgeBeingEditedId]; + this.selectedControlNode = undefined; + + var fromSelect = from.isOverlappingWith(pointerObj); + var toSelect = to.isOverlappingWith(pointerObj); + + if (fromSelect === true) { + this.selectedControlNode = from; + edge.edgeType.from = from; + } else if (toSelect === true) { + this.selectedControlNode = to; + edge.edgeType.to = to; + } - /** - * the drag start is used to mark one of the control nodes as selected. - * @param event - * @private - */ - value: function _controlNodeDragStart(event) { - var pointer = this.lastTouch; - var pointerObj = this.selectionHandler._pointerToPositionObject(pointer); - var from = this.body.nodes[this.temporaryIds.nodes[0]]; - var to = this.body.nodes[this.temporaryIds.nodes[1]]; - var edge = this.body.edges[this.edgeBeingEditedId]; - this.selectedControlNode = undefined; - - var fromSelect = from.isOverlappingWith(pointerObj); - var toSelect = to.isOverlappingWith(pointerObj); - - if (fromSelect === true) { - this.selectedControlNode = from; - edge.edgeType.from = from; - } else if (toSelect === true) { - this.selectedControlNode = to; - edge.edgeType.to = to; - } - - this.body.emitter.emit("_redraw"); - }, - writable: true, - configurable: true - }, - _controlNodeDrag: { + this.body.emitter.emit('_redraw'); + } + }, { + key: '_controlNodeDrag', - /** - * dragging the control nodes or the canvas - * @param event - * @private - */ - value: function _controlNodeDrag(event) { - this.body.emitter.emit("disablePhysics"); - var pointer = this.body.functions.getPointer(event.center); - var pos = this.canvas.DOMtoCanvas(pointer); + /** + * dragging the control nodes or the canvas + * @param event + * @private + */ + value: function _controlNodeDrag(event) { + this.body.emitter.emit('disablePhysics'); + var pointer = this.body.functions.getPointer(event.center); + var pos = this.canvas.DOMtoCanvas(pointer); + + if (this.selectedControlNode !== undefined) { + this.selectedControlNode.x = pos.x; + this.selectedControlNode.y = pos.y; + } else { + // if the drag was not started properly because the click started outside the network div, start it now. + var diffX = pointer.x - this.lastTouch.x; + var diffY = pointer.y - this.lastTouch.y; + this.body.view.translation = { x: this.lastTouch.translation.x + diffX, y: this.lastTouch.translation.y + diffY }; + } + this.body.emitter.emit('_redraw'); + } + }, { + key: '_controlNodeDragEnd', + + /** + * connecting or restoring the control nodes. + * @param event + * @private + */ + value: function _controlNodeDragEnd(event) { + var pointer = this.body.functions.getPointer(event.center); + var pointerObj = this.selectionHandler._pointerToPositionObject(pointer); + var edge = this.body.edges[this.edgeBeingEditedId]; + + var overlappingNodeIds = this.selectionHandler._getAllNodesOverlappingWith(pointerObj); + var node = undefined; + for (var i = overlappingNodeIds.length - 1; i >= 0; i--) { + if (overlappingNodeIds[i] !== this.selectedControlNode.id) { + node = this.body.nodes[overlappingNodeIds[i]]; + break; + } + } - if (this.selectedControlNode !== undefined) { - this.selectedControlNode.x = pos.x; - this.selectedControlNode.y = pos.y; + // perform the connection + if (node !== undefined && this.selectedControlNode !== undefined) { + if (node.isCluster === true) { + alert(this.options.locales[this.options.locale].createEdgeError); } else { - // if the drag was not started properly because the click started outside the network div, start it now. - var diffX = pointer.x - this.lastTouch.x; - var diffY = pointer.y - this.lastTouch.y; - this.body.view.translation = { x: this.lastTouch.translation.x + diffX, y: this.lastTouch.translation.y + diffY }; + var from = this.body.nodes[this.temporaryIds.nodes[0]]; + if (this.selectedControlNode.id === from.id) { + this._performEditEdge(node.id, edge.to.id); + } else { + this._performEditEdge(edge.from.id, node.id); + } } - this.body.emitter.emit("_redraw"); - }, - writable: true, - configurable: true - }, - _controlNodeDragEnd: { + } else { + edge.updateEdgeType(); + this.body.emitter.emit('restorePhysics'); + } + this.body.emitter.emit('_redraw'); + } + }, { + key: '_handleConnect', + // ------------------------------------ END OF EDIT EDGE FUNCTIONS -----------------------------------------// - /** - * connecting or restoring the control nodes. - * @param event - * @private - */ - value: function _controlNodeDragEnd(event) { - var pointer = this.body.functions.getPointer(event.center); - var pointerObj = this.selectionHandler._pointerToPositionObject(pointer); - var edge = this.body.edges[this.edgeBeingEditedId]; + // ------------------------------------------- ADD EDGE FUNCTIONS -----------------------------------------// + /** + * 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 + */ + value: function _handleConnect(event) { + var _this3 = this; - var overlappingNodeIds = this.selectionHandler._getAllNodesOverlappingWith(pointerObj); - var node = undefined; - for (var i = overlappingNodeIds.length - 1; i >= 0; i--) { - if (overlappingNodeIds[i] !== this.selectedControlNode.id) { - node = this.body.nodes[overlappingNodeIds[i]]; - break; - } - } + // check to avoid double fireing of this function. + if (new Date().valueOf() - this.touchTime > 100) { + var pointer = this.body.functions.getPointer(event.center); + var node = this.selectionHandler.getNodeAt(pointer); - // perform the connection - if (node !== undefined && this.selectedControlNode !== undefined) { + if (node !== undefined) { if (node.isCluster === true) { alert(this.options.locales[this.options.locale].createEdgeError); } else { - var from = this.body.nodes[this.temporaryIds.nodes[0]]; - if (this.selectedControlNode.id === from.id) { - this._performEditEdge(node.id, edge.to.id); - } else { - this._performEditEdge(edge.from.id, node.id); - } + (function () { + // create a node the temporary line can look at + var targetNode = _this3._getNewTargetNode(node.x, node.y); + var targetNodeId = targetNode.id; + _this3.body.nodes[targetNode.id] = targetNode; + _this3.body.nodeIndices.push(targetNode.id); + + // create a temporary edge + var connectionEdge = _this3.body.functions.createEdge({ + id: 'connectionEdge' + util.randomUUID(), + from: node.id, + to: targetNode.id, + physics: false, + smooth: { + enabled: true, + dynamic: false, + type: 'continuous', + roundness: 0.5 + } + }); + _this3.body.edges[connectionEdge.id] = connectionEdge; + _this3.body.edgeIndices.push(connectionEdge.id); + + _this3.temporaryIds.nodes.push(targetNode.id); + _this3.temporaryIds.edges.push(connectionEdge.id); + + _this3.temporaryUIFunctions.onDrag = _this3.body.eventListeners.onDrag; + _this3.body.eventListeners.onDrag = function (event) { + var pointer = _this3.body.functions.getPointer(event.center); + var targetNode = _this3.body.nodes[targetNodeId]; + targetNode.x = _this3.canvas._XconvertDOMtoCanvas(pointer.x); + targetNode.y = _this3.canvas._YconvertDOMtoCanvas(pointer.y); + _this3.body.emitter.emit('_redraw'); + }; + })(); } - } else { - edge.updateEdgeType(); - this.body.emitter.emit("restorePhysics"); } - this.body.emitter.emit("_redraw"); - }, - writable: true, - configurable: true - }, - _handleConnect: { - - // ------------------------------------ END OF EDIT EDGE FUNCTIONS -----------------------------------------// + this.touchTime = new Date().valueOf(); + // do the original touch events + this.temporaryUIFunctions.onTouch(event); + } + } + }, { + key: '_finishConnect', + /** + * Connect the new edge to the target if one exists, otherwise remove temp line + * @param event + * @private + */ + value: function _finishConnect(event) { + var pointer = this.body.functions.getPointer(event.center); + var pointerObj = this.selectionHandler._pointerToPositionObject(pointer); + + // remember the edge id + var connectFromId = undefined; + if (this.temporaryIds.edges[0] !== undefined) { + connectFromId = this.body.edges[this.temporaryIds.edges[0]].fromId; + } - // ------------------------------------------- ADD EDGE FUNCTIONS -----------------------------------------// - /** - * 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 - */ - value: function _handleConnect(event) { - var _this = this; - // check to avoid double fireing of this function. - if (new Date().valueOf() - this.touchTime > 100) { - var pointer = this.body.functions.getPointer(event.center); - var node = this.selectionHandler.getNodeAt(pointer); - - if (node !== undefined) { - if (node.isCluster === true) { - alert(this.options.locales[this.options.locale].createEdgeError); - } else { - (function () { - // create a node the temporary line can look at - var targetNode = _this._getNewTargetNode(node.x, node.y); - var targetNodeId = targetNode.id; - _this.body.nodes[targetNode.id] = targetNode; - _this.body.nodeIndices.push(targetNode.id); - - // create a temporary edge - var connectionEdge = _this.body.functions.createEdge({ - id: "connectionEdge" + util.randomUUID(), - from: node.id, - to: targetNode.id, - physics: false, - smooth: { - enabled: true, - dynamic: false, - type: "continuous", - roundness: 0.5 - } - }); - _this.body.edges[connectionEdge.id] = connectionEdge; - _this.body.edgeIndices.push(connectionEdge.id); - - _this.temporaryIds.nodes.push(targetNode.id); - _this.temporaryIds.edges.push(connectionEdge.id); - - _this.temporaryUIFunctions.onDrag = _this.body.eventListeners.onDrag; - _this.body.eventListeners.onDrag = function (event) { - var pointer = _this.body.functions.getPointer(event.center); - var targetNode = _this.body.nodes[targetNodeId]; - targetNode.x = _this.canvas._XconvertDOMtoCanvas(pointer.x); - targetNode.y = _this.canvas._YconvertDOMtoCanvas(pointer.y); - _this.body.emitter.emit("_redraw"); - }; - })(); - } - } - this.touchTime = new Date().valueOf(); + //restore the drag function + if (this.temporaryUIFunctions.onDrag !== undefined) { + this.body.eventListeners.onDrag = this.temporaryUIFunctions.onDrag; + delete this.temporaryUIFunctions.onDrag; + } - // do the original touch events - this.temporaryUIFunctions.onTouch(event); + // get the overlapping node but NOT the temporary node; + var overlappingNodeIds = this.selectionHandler._getAllNodesOverlappingWith(pointerObj); + var node = undefined; + for (var i = overlappingNodeIds.length - 1; i >= 0; i--) { + if (this.temporaryIds.nodes.indexOf(overlappingNodeIds[i]) !== -1) { + node = this.body.nodes[overlappingNodeIds[i]]; + break; } - }, - writable: true, - configurable: true - }, - _finishConnect: { + } - /** - * Connect the new edge to the target if one exists, otherwise remove temp line - * @param event - * @private - */ - value: function _finishConnect(event) { - var pointer = this.body.functions.getPointer(event.center); - var pointerObj = this.selectionHandler._pointerToPositionObject(pointer); + // clean temporary nodes and edges. + this._cleanupTemporaryNodesAndEdges(); - // remember the edge id - var connectFromId = undefined; - if (this.temporaryIds.edges[0] !== undefined) { - connectFromId = this.body.edges[this.temporaryIds.edges[0]].fromId; + // perform the connection + if (node !== undefined) { + if (node.isCluster === true) { + alert(this.options.locales[this.options.locale].createEdgeError); + } else { + if (this.body.nodes[connectFromId] !== undefined && this.body.nodes[node.id] !== undefined) { + this._performCreateEdge(connectFromId, node.id); + } } + } + this.body.emitter.emit('_redraw'); + } + }, { + key: '_performAddNode', - //restore the drag function - if (this.temporaryUIFunctions.onDrag !== undefined) { - this.body.eventListeners.onDrag = this.temporaryUIFunctions.onDrag; - delete this.temporaryUIFunctions.onDrag; - } + // --------------------------------------- END OF ADD EDGE FUNCTIONS -------------------------------------// - // get the overlapping node but NOT the temporary node; - var overlappingNodeIds = this.selectionHandler._getAllNodesOverlappingWith(pointerObj); - var node = undefined; - for (var i = overlappingNodeIds.length - 1; i >= 0; i--) { - if (this.temporaryIds.nodes.indexOf(overlappingNodeIds[i]) !== -1) { - node = this.body.nodes[overlappingNodeIds[i]]; - break; - } - } - - // clean temporary nodes and edges. - this._cleanupTemporaryNodesAndEdges(); - - // perform the connection - if (node !== undefined) { - if (node.isCluster === true) { - alert(this.options.locales[this.options.locale].createEdgeError); - } else { - if (this.body.nodes[connectFromId] !== undefined && this.body.nodes[node.id] !== undefined) { - this._performCreateEdge(connectFromId, node.id); - } - } - } - this.body.emitter.emit("_redraw"); - }, - writable: true, - configurable: true - }, - _performAddNode: { - - // --------------------------------------- END OF ADD EDGE FUNCTIONS -------------------------------------// - - - // ------------------------------ Performing all the actual data manipulation ------------------------// + // ------------------------------ Performing all the actual data manipulation ------------------------// - /** - * Adds a node on the specified location - */ - value: function _performAddNode(clickData) { - var _this = this; - var defaultData = { - id: util.randomUUID(), - x: clickData.pointer.canvas.x, - y: clickData.pointer.canvas.y, - label: "new" - }; + /** + * Adds a node on the specified location + */ + value: function _performAddNode(clickData) { + var _this4 = this; + + var defaultData = { + id: util.randomUUID(), + x: clickData.pointer.canvas.x, + y: clickData.pointer.canvas.y, + label: 'new' + }; - if (typeof this.options.handlerFunctions.addNode === "function") { - if (this.options.handlerFunctions.addNode.length === 2) { - this.options.handlerFunctions.addNode(defaultData, function (finalizedData) { - _this.body.data.nodes.add(finalizedData); - _this.showManipulatorToolbar(); - }); - } else { - throw new Error("The function for add does not support two arguments (data,callback)"); - this.showManipulatorToolbar(); - } + if (typeof this.options.handlerFunctions.addNode === 'function') { + if (this.options.handlerFunctions.addNode.length === 2) { + this.options.handlerFunctions.addNode(defaultData, function (finalizedData) { + _this4.body.data.nodes.add(finalizedData); + _this4.showManipulatorToolbar(); + }); } else { - this.body.data.nodes.add(defaultData); + throw new Error('The function for add does not support two arguments (data,callback)'); this.showManipulatorToolbar(); } - }, - writable: true, - configurable: true - }, - _performCreateEdge: { - + } else { + this.body.data.nodes.add(defaultData); + this.showManipulatorToolbar(); + } + } + }, { + key: '_performCreateEdge', - /** - * connect two nodes with a new edge. - * - * @private - */ - value: function _performCreateEdge(sourceNodeId, targetNodeId) { - var _this = this; - var defaultData = { from: sourceNodeId, to: targetNodeId }; - if (this.options.handlerFunctions.addEdge) { - if (this.options.handlerFunctions.addEdge.length === 2) { - this.options.handlerFunctions.addEdge(defaultData, function (finalizedData) { - _this.body.data.edges.add(finalizedData); - _this.selectionHandler.unselectAll(); - _this.showManipulatorToolbar(); - }); - } else { - throw new Error("The function for connect does not support two arguments (data,callback)"); - } + /** + * connect two nodes with a new edge. + * + * @private + */ + value: function _performCreateEdge(sourceNodeId, targetNodeId) { + var _this5 = this; + + var defaultData = { from: sourceNodeId, to: targetNodeId }; + if (this.options.handlerFunctions.addEdge) { + if (this.options.handlerFunctions.addEdge.length === 2) { + this.options.handlerFunctions.addEdge(defaultData, function (finalizedData) { + _this5.body.data.edges.add(finalizedData); + _this5.selectionHandler.unselectAll(); + _this5.showManipulatorToolbar(); + }); } else { - this.body.data.edges.add(defaultData); - this.selectionHandler.unselectAll(); - this.showManipulatorToolbar(); + throw new Error('The function for connect does not support two arguments (data,callback)'); } - }, - writable: true, - configurable: true - }, - _performEditEdge: { + } else { + this.body.data.edges.add(defaultData); + this.selectionHandler.unselectAll(); + this.showManipulatorToolbar(); + } + } + }, { + key: '_performEditEdge', - /** - * connect two nodes with a new edge. - * - * @private - */ - value: function _performEditEdge(sourceNodeId, targetNodeId) { - var _this = this; - var defaultData = { id: this.edgeBeingEditedId, from: sourceNodeId, to: targetNodeId }; - if (this.options.handlerFunctions.editEdge) { - if (this.options.handlerFunctions.editEdge.length === 2) { - this.options.handlerFunctions.editEdge(defaultData, function (finalizedData) { - _this.body.data.edges.update(finalizedData); - _this.selectionHandler.unselectAll(); - _this.showManipulatorToolbar(); - }); - } else { - throw new Error("The function for edit does not support two arguments (data, callback)"); - } + /** + * connect two nodes with a new edge. + * + * @private + */ + value: function _performEditEdge(sourceNodeId, targetNodeId) { + var _this6 = this; + + var defaultData = { id: this.edgeBeingEditedId, from: sourceNodeId, to: targetNodeId }; + if (this.options.handlerFunctions.editEdge) { + if (this.options.handlerFunctions.editEdge.length === 2) { + this.options.handlerFunctions.editEdge(defaultData, function (finalizedData) { + _this6.body.data.edges.update(finalizedData); + _this6.selectionHandler.unselectAll(); + _this6.showManipulatorToolbar(); + }); } else { - this.body.data.edges.update(defaultData); - this.selectionHandler.unselectAll(); - this.showManipulatorToolbar(); + throw new Error('The function for edit does not support two arguments (data, callback)'); } - }, - writable: true, - configurable: true + } else { + this.body.data.edges.update(defaultData); + this.selectionHandler.unselectAll(); + this.showManipulatorToolbar(); + } } - }); + }]); return ManipulationSystem; })(); - module.exports = ManipulationSystem; + exports['default'] = ManipulationSystem; + module.exports = exports['default']; /***/ }, -/* 62 */ +/* 61 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; - var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); - var util = __webpack_require__(1); + Object.defineProperty(exports, '__esModule', { + value: true + }); + + var _ColorPicker = __webpack_require__(80); + + var _ColorPicker2 = _interopRequireWildcard(_ColorPicker); - var ColorPicker = _interopRequire(__webpack_require__(96)); + var util = __webpack_require__(1); var ConfigurationSystem = (function () { function ConfigurationSystem(network) { @@ -24285,15 +24490,15 @@ return /******/ (function(modules) { // webpackBootstrap borderWidth: [1, 0, 10, 1], borderWidthSelected: [2, 0, 10, 1], color: { - border: ["color", "#2B7CE9"], - background: ["color", "#97C2FC"], + border: ['color', '#2B7CE9'], + background: ['color', '#97C2FC'], highlight: { - border: ["color", "#2B7CE9"], - background: ["color", "#D2E5FF"] + border: ['color', '#2B7CE9'], + background: ['color', '#D2E5FF'] }, hover: { - border: ["color", "#2B7CE9"], - background: ["color", "#D2E5FF"] + border: ['color', '#2B7CE9'], + background: ['color', '#D2E5FF'] } }, fixed: { @@ -24301,12 +24506,12 @@ return /******/ (function(modules) { // webpackBootstrap y: false }, font: { - color: ["color", "#343434"], + color: ['color', '#343434'], size: [14, 0, 100, 1], // px - face: ["arial", "verdana", "tahoma"], - background: ["color", "none"], + face: ['arial', 'verdana', 'tahoma'], + background: ['color', 'none'], stroke: [0, 0, 50, 1], // px - strokeColor: ["color", "#ffffff"] + strokeColor: ['color', '#ffffff'] }, //group: 'string', hidden: false, @@ -24329,7 +24534,7 @@ return /******/ (function(modules) { // webpackBootstrap drawThreshold: [3, 0, 20, 1] } }, - shape: ["ellipse", "box", "circle", "database", "diamond", "dot", "square", "star", "text", "triangle", "triangleDown"], + shape: ['ellipse', 'box', 'circle', 'database', 'diamond', 'dot', 'square', 'star', 'text', 'triangle', 'triangleDown'], size: [25, 0, 200, 1] }, edges: { @@ -24339,12 +24544,12 @@ return /******/ (function(modules) { // webpackBootstrap from: { enabled: false, scaleFactor: [1, 0, 3, 0.05] } }, color: { - color: ["color", "#848484"], - highlight: ["color", "#848484"], - hover: ["color", "#848484"], + color: ['color', '#848484'], + highlight: ['color', '#848484'], + hover: ['color', '#848484'], inherit: { enabled: true, - source: ["from", "to"], // from / to + source: ['from', 'to'], // from / to useGradients: false }, opacity: [1, 0, 1, 0.05] @@ -24356,13 +24561,13 @@ return /******/ (function(modules) { // webpackBootstrap altLength: [5, 0, 50, 1] }, font: { - color: ["color", "#343434"], + color: ['color', '#343434'], size: [14, 0, 100, 1], // px - face: ["arial", "verdana", "tahoma"], - background: ["color", "none"], + face: ['arial', 'verdana', 'tahoma'], + background: ['color', 'none'], stroke: [1, 0, 50, 1], // px - strokeColor: ["color", "#ffffff"], - align: ["horizontal", "top", "middle", "bottom"] + strokeColor: ['color', '#ffffff'], + align: ['horizontal', 'top', 'middle', 'bottom'] }, hidden: false, hoverWidth: [1.5, 0, 10, 0.1], @@ -24382,7 +24587,7 @@ return /******/ (function(modules) { // webpackBootstrap smooth: { enabled: true, dynamic: true, - type: ["continuous", "discrete", "diagonalCross", "straightCross", "horizontal", "vertical", "curvedCW", "curvedCCW"], + type: ['continuous', 'discrete', 'diagonalCross', 'straightCross', 'horizontal', 'vertical', 'curvedCW', 'curvedCCW'], roundness: [0.5, 0, 1, 0.05] }, width: [1, 0, 30, 1], @@ -24393,8 +24598,8 @@ return /******/ (function(modules) { // webpackBootstrap hierarchical: { enabled: false, levelSeparation: [150, 20, 500, 5], - direction: ["UD", "DU", "LR", "RL"], // UD, DU, LR, RL - sortMethod: ["hubsize", "directed"] // hubsize, directed + direction: ['UD', 'DU', 'LR', 'RL'], // UD, DU, LR, RL + sortMethod: ['hubsize', 'directed'] // hubsize, directed } }, interaction: { @@ -24405,12 +24610,12 @@ return /******/ (function(modules) { // webpackBootstrap showNavigationIcons: false, tooltip: { delay: [300, 0, 1000, 25], - fontColor: ["color", "#000000"], + fontColor: ['color', '#000000'], fontSize: [14, 0, 40, 1], // px - fontFace: ["arial", "verdana", "tahoma"], + fontFace: ['arial', 'verdana', 'tahoma'], color: { - border: ["color", "#666666"], - background: ["color", "#FFFFC6"] + border: ['color', '#666666'], + background: ['color', '#FFFFC6'] } }, keyboard: { @@ -24422,7 +24627,7 @@ return /******/ (function(modules) { // webpackBootstrap manipulation: { enabled: false, initiallyVisible: false, - locale: ["en", "nl"], + locale: ['en', 'nl'], functionality: { addNode: true, addEdge: true, @@ -24457,7 +24662,7 @@ return /******/ (function(modules) { // webpackBootstrap }, maxVelocity: [50, 0, 150, 1], minVelocity: [0.1, 0.01, 0.5, 0.01], - solver: ["barnesHut", "repulsion", "hierarchicalRepulsion"], + solver: ['barnesHut', 'repulsion', 'hierarchicalRepulsion'], timestep: [0.5, 0, 1, 0.05] }, selection: { @@ -24484,732 +24689,1114 @@ return /******/ (function(modules) { // webpackBootstrap }; this.domElements = []; - this.colorPicker = new ColorPicker(this.network.canvas.pixelRatio); + this.colorPicker = new _ColorPicker2['default'](this.network.canvas.pixelRatio); } - _prototypeProperties(ConfigurationSystem, null, { - setOptions: { - + _createClass(ConfigurationSystem, [{ + key: 'setOptions', - /** - * refresh all options. - * Because all modules parse their options by themselves, we just use their options. We copy them here. - * - * @param options - */ - value: function setOptions(options) { - if (options !== undefined) { - util.extend(this.actualOptions, options); - } + /** + * refresh all options. + * Because all modules parse their options by themselves, we just use their options. We copy them here. + * + * @param options + */ + value: function setOptions(options) { + if (options !== undefined) { + util.extend(this.actualOptions, options); + } - this._clean(); + this._clean(); - if (this.actualOptions.configure !== undefined && this.actualOptions.configure !== false) { - util.deepExtend(this.actualOptions.nodes, this.network.nodesHandler.options, true); - util.deepExtend(this.actualOptions.edges, this.network.edgesHandler.options, true); - util.deepExtend(this.actualOptions.layout, this.network.layoutEngine.options, true); - util.deepExtend(this.actualOptions.interaction, this.network.interactionHandler.options, true); - util.deepExtend(this.actualOptions.manipulation, this.network.manipulation.options, true); - util.deepExtend(this.actualOptions.physics, this.network.physics.options, true); - util.deepExtend(this.actualOptions.selection, this.network.selectionHandler.selection, true); - util.deepExtend(this.actualOptions.renderer, this.network.renderer.selection, true); + if (this.actualOptions.configure !== undefined && this.actualOptions.configure !== false) { + util.deepExtend(this.actualOptions.nodes, this.network.nodesHandler.options, true); + util.deepExtend(this.actualOptions.edges, this.network.edgesHandler.options, true); + util.deepExtend(this.actualOptions.layout, this.network.layoutEngine.options, true); + util.deepExtend(this.actualOptions.interaction, this.network.interactionHandler.options, true); + util.deepExtend(this.actualOptions.manipulation, this.network.manipulation.options, true); + util.deepExtend(this.actualOptions.physics, this.network.physics.options, true); + util.deepExtend(this.actualOptions.selection, this.network.selectionHandler.selection, true); + util.deepExtend(this.actualOptions.renderer, this.network.renderer.selection, true); - if (this.actualOptions.configurationContainer !== undefined) { - this.container = this.actualOptions.configurationContainer; - } else { - this.container = this.network.body.container; - } + if (this.actualOptions.configurationContainer !== undefined) { + this.container = this.actualOptions.configurationContainer; + } else { + this.container = this.network.body.container; + } - var config = undefined; - if (this.actualOptions.configure instanceof Array) { - config = this.actualOptions.configure.join(); - } else if (typeof this.actualOptions.configure === "string") { - config = this.actualOptions.configure; - } else if (typeof this.actualOptions.configure === "boolean") { - config = this.actualOptions.configure; - } else { - this._clean(); - throw new Error("the option for configure has to be either a string, boolean or an array. Supplied:" + this.options.configure); - return; - } - this._create(config); + var config = undefined; + if (this.actualOptions.configure instanceof Array) { + config = this.actualOptions.configure.join(); + } else if (typeof this.actualOptions.configure === 'string') { + config = this.actualOptions.configure; + } else if (typeof this.actualOptions.configure === 'boolean') { + config = this.actualOptions.configure; + } else { + this._clean(); + throw new Error('the option for configure has to be either a string, boolean or an array. Supplied:' + this.options.configure); + return; } - }, - writable: true, - configurable: true - }, - _create: { + this._create(config); + } + } + }, { + key: '_create', - /** - * Create all DOM elements - * @param {Boolean | String} config - * @private - */ - value: function _create(config) { - var _this = this; - this._clean(); - this.changedOptions = []; - - var counter = 0; - for (var option in this.possibleOptions) { - if (this.possibleOptions.hasOwnProperty(option)) { - if (config === true || config.indexOf(option) !== -1) { - var optionObj = this.possibleOptions[option]; - - // linebreak between categories - if (counter > 0) { - this._makeEntree([]); - } - // a header for the category - this._makeHeader(option); + /** + * Create all DOM elements + * @param {Boolean | String} config + * @private + */ + value: function _create(config) { + var _this = this; + + this._clean(); + this.changedOptions = []; - // get the suboptions - var path = [option]; - this._handleObject(optionObj, path); + var counter = 0; + for (var option in this.possibleOptions) { + if (this.possibleOptions.hasOwnProperty(option)) { + if (config === true || config.indexOf(option) !== -1) { + var optionObj = this.possibleOptions[option]; + + // linebreak between categories + if (counter > 0) { + this._makeEntree([]); } - counter++; + // a header for the category + this._makeHeader(option); + + // get the suboptions + var path = [option]; + this._handleObject(optionObj, path); } + counter++; } - var generateButton = document.createElement("div"); - generateButton.className = "vis-network-configuration button"; - generateButton.innerHTML = "generate options"; - generateButton.onclick = function () { - _this._printOptions(); - }; - generateButton.onmouseover = function () { - generateButton.className = "vis-network-configuration button hover"; - }; - generateButton.onmouseout = function () { - generateButton.className = "vis-network-configuration button"; - }; - - this.optionsContainer = document.createElement("div"); - this.optionsContainer.className = "vis-network-configuration optionContainer"; + } + var generateButton = document.createElement('div'); + generateButton.className = 'vis-network-configuration button'; + generateButton.innerHTML = 'generate options'; + generateButton.onclick = function () { + _this._printOptions(); + }; + generateButton.onmouseover = function () { + generateButton.className = 'vis-network-configuration button hover'; + }; + generateButton.onmouseout = function () { + generateButton.className = 'vis-network-configuration button'; + }; - this.domElements.push(this.optionsContainer); - this.domElements.push(generateButton); + this.optionsContainer = document.createElement('div'); + this.optionsContainer.className = 'vis-network-configuration optionContainer'; - this._push(); - this.colorPicker.insertTo(this.container); - }, - writable: true, - configurable: true - }, - _push: { + this.domElements.push(this.optionsContainer); + this.domElements.push(generateButton); + this._push(); + this.colorPicker.insertTo(this.container); + } + }, { + key: '_push', - /** - * draw all DOM elements on the screen - * @private - */ - value: function _push() { - for (var i = 0; i < this.domElements.length; i++) { - this.container.appendChild(this.domElements[i]); - } - }, - writable: true, - configurable: true - }, - _clean: { + /** + * draw all DOM elements on the screen + * @private + */ + value: function _push() { + for (var i = 0; i < this.domElements.length; i++) { + this.container.appendChild(this.domElements[i]); + } + } + }, { + key: '_clean', - /** - * delete all DOM elements - * @private - */ - value: function _clean() { - for (var i = 0; i < this.domElements.length; i++) { - this.container.removeChild(this.domElements[i]); - } - this.domElements = []; - }, - writable: true, - configurable: true - }, - _getValue: { + /** + * delete all DOM elements + * @private + */ + value: function _clean() { + for (var i = 0; i < this.domElements.length; i++) { + this.container.removeChild(this.domElements[i]); + } + this.domElements = []; + } + }, { + key: '_getValue', - /** - * get the value from the actualOptions if it exists - * @param {array} path | where to look for the actual option - * @returns {*} - * @private - */ - value: function _getValue(path) { - var base = this.actualOptions; - for (var i = 0; i < path.length; i++) { - if (base[path[i]] !== undefined) { - base = base[path[i]]; - } else { - base = undefined; - break; - } + /** + * get the value from the actualOptions if it exists + * @param {array} path | where to look for the actual option + * @returns {*} + * @private + */ + value: function _getValue(path) { + var base = this.actualOptions; + for (var i = 0; i < path.length; i++) { + if (base[path[i]] !== undefined) { + base = base[path[i]]; + } else { + base = undefined; + break; } - return base; - }, - writable: true, - configurable: true - }, - _addToPath: { - + } + return base; + } + }, { + key: '_addToPath', - /** - * Copy the path and add a step. It needs to copy because the path will keep stacking otherwise. - * @param path - * @param newValue - * @returns {Array} - * @private - */ - value: function _addToPath(path, newValue) { - var newPath = []; - for (var i = 0; i < path.length; i++) { - newPath.push(path[i]); - } - newPath.push(newValue); - return newPath; - }, - writable: true, - configurable: true - }, - _makeEntree: { + /** + * Copy the path and add a step. It needs to copy because the path will keep stacking otherwise. + * @param path + * @param newValue + * @returns {Array} + * @private + */ + value: function _addToPath(path, newValue) { + var newPath = []; + for (var i = 0; i < path.length; i++) { + newPath.push(path[i]); + } + newPath.push(newValue); + return newPath; + } + }, { + key: '_makeEntree', - /** - * all option elements are wrapped in an entree - * @param path - * @param domElements - * @private - */ - value: function _makeEntree(path) { - for (var _len = arguments.length, domElements = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - domElements[_key - 1] = arguments[_key]; - } + /** + * all option elements are wrapped in an entree + * @param path + * @param domElements + * @private + */ + value: function _makeEntree(path) { + for (var _len = arguments.length, domElements = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + domElements[_key - 1] = arguments[_key]; + } - var entree = document.createElement("div"); - entree.className = "vis-network-configuration entree s" + path.length; - domElements.forEach(function (element) { - entree.appendChild(element); - }); - this.domElements.push(entree); - }, - writable: true, - configurable: true - }, - _makeHeader: { + var entree = document.createElement('div'); + entree.className = 'vis-network-configuration entree s' + path.length; + domElements.forEach(function (element) { + entree.appendChild(element); + }); + this.domElements.push(entree); + } + }, { + key: '_makeHeader', - /** - * header for major subjects - * @param name - * @private - */ - value: function _makeHeader(name) { - var div = document.createElement("div"); - div.className = "vis-network-configuration header"; - div.innerHTML = name; - this._makeEntree([], div); - }, - writable: true, - configurable: true - }, - _makeLabel: { + /** + * header for major subjects + * @param name + * @private + */ + value: function _makeHeader(name) { + var div = document.createElement('div'); + div.className = 'vis-network-configuration header'; + div.innerHTML = name; + this._makeEntree([], div); + } + }, { + key: '_makeLabel', - /** - * make a label, if it is an object label, it gets different styling. - * @param name - * @param path - * @param objectLabel - * @returns {HTMLElement} - * @private - */ - value: function _makeLabel(name, path) { - var objectLabel = arguments[2] === undefined ? false : arguments[2]; - var div = document.createElement("div"); - div.className = "vis-network-configuration label s" + path.length; - if (objectLabel === true) { - div.innerHTML = "" + name + ":"; - } else { - div.innerHTML = name + ":"; - } - return div; - }, - writable: true, - configurable: true - }, - _makeDropdown: { + /** + * make a label, if it is an object label, it gets different styling. + * @param name + * @param path + * @param objectLabel + * @returns {HTMLElement} + * @private + */ + value: function _makeLabel(name, path) { + var objectLabel = arguments[2] === undefined ? false : arguments[2]; + var div = document.createElement('div'); + div.className = 'vis-network-configuration label s' + path.length; + if (objectLabel === true) { + div.innerHTML = '' + name + ':'; + } else { + div.innerHTML = name + ':'; + } + return div; + } + }, { + key: '_makeDropdown', - /** - * make a dropdown list for multiple possible string optoins - * @param arr - * @param value - * @param path - * @private - */ - value: function _makeDropdown(arr, value, path) { - var select = document.createElement("select"); - select.className = "vis-network-configuration select"; - var selectedValue = 0; - if (value !== undefined) { - if (arr.indexOf(value) !== -1) { - selectedValue = arr.indexOf(value); - } + /** + * make a dropdown list for multiple possible string optoins + * @param arr + * @param value + * @param path + * @private + */ + value: function _makeDropdown(arr, value, path) { + var select = document.createElement('select'); + select.className = 'vis-network-configuration select'; + var selectedValue = 0; + if (value !== undefined) { + if (arr.indexOf(value) !== -1) { + selectedValue = arr.indexOf(value); } + } - for (var i = 0; i < arr.length; i++) { - var option = document.createElement("option"); - option.value = arr[i]; - if (i === selectedValue) { - option.selected = "selected"; - } - option.innerHTML = arr[i]; - select.appendChild(option); + for (var i = 0; i < arr.length; i++) { + var option = document.createElement('option'); + option.value = arr[i]; + if (i === selectedValue) { + option.selected = 'selected'; } + option.innerHTML = arr[i]; + select.appendChild(option); + } - var me = this; - select.onchange = function () { - me._update(this.value, path); - }; + var me = this; + select.onchange = function () { + me._update(this.value, path); + }; - var label = this._makeLabel(path[path.length - 1], path); - this._makeEntree(path, label, select); - }, - writable: true, - configurable: true - }, - _makeRange: { + var label = this._makeLabel(path[path.length - 1], path); + this._makeEntree(path, label, select); + } + }, { + key: '_makeRange', + /** + * make a range object for numeric options + * @param arr + * @param value + * @param path + * @private + */ + value: function _makeRange(arr, value, path) { + var defaultValue = arr[0]; + var min = arr[1]; + var max = arr[2]; + var step = arr[3]; + var range = document.createElement('input'); + range.type = 'range'; + range.className = 'vis-network-configuration range'; + range.min = min; + range.max = max; + range.step = step; - /** - * make a range object for numeric options - * @param arr - * @param value - * @param path - * @private - */ - value: function _makeRange(arr, value, path) { - var defaultValue = arr[0]; - var min = arr[1]; - var max = arr[2]; - var step = arr[3]; - var range = document.createElement("input"); - range.type = "range"; - range.className = "vis-network-configuration range"; - range.min = min; - range.max = max; - range.step = step; - - if (value !== undefined) { - if (value * 0.1 < min) { - range.min = value / 10; - } - if (value * 2 > max && max !== 1) { - range.max = value * 2; - } - range.value = value; - } else { - range.value = defaultValue; + if (value !== undefined) { + if (value * 0.1 < min) { + range.min = value / 10; } + if (value * 2 > max && max !== 1) { + range.max = value * 2; + } + range.value = value; + } else { + range.value = defaultValue; + } - var input = document.createElement("input"); - input.className = "vis-network-configuration rangeinput"; - input.value = range.value; - - var me = this; - range.onchange = function () { - input.value = this.value;me._update(this.value, path); - }; - range.oninput = function () { - input.value = this.value; - }; + var input = document.createElement('input'); + input.className = 'vis-network-configuration rangeinput'; + input.value = range.value; - var label = this._makeLabel(path[path.length - 1], path); - this._makeEntree(path, label, range, input); - }, - writable: true, - configurable: true - }, - _makeCheckbox: { + var me = this; + range.onchange = function () { + input.value = this.value;me._update(this.value, path); + }; + range.oninput = function () { + input.value = this.value; + }; + var label = this._makeLabel(path[path.length - 1], path); + this._makeEntree(path, label, range, input); + } + }, { + key: '_makeCheckbox', - /** - * make a checkbox for boolean options. - * @param defaultValue - * @param value - * @param path - * @private - */ - value: function _makeCheckbox(defaultValue, value, path) { - var checkbox = document.createElement("input"); - checkbox.type = "checkbox"; - checkbox.className = "vis-network-configuration checkbox"; - checkbox.checked = defaultValue; - if (value !== undefined) { - checkbox.checked = value; - if (value !== defaultValue) { - if (typeof defaultValue === "object") { - if (value !== defaultValue.enabled) { - this.changedOptions.push({ path: path, value: value }); - } - } else { + /** + * make a checkbox for boolean options. + * @param defaultValue + * @param value + * @param path + * @private + */ + value: function _makeCheckbox(defaultValue, value, path) { + var checkbox = document.createElement('input'); + checkbox.type = 'checkbox'; + checkbox.className = 'vis-network-configuration checkbox'; + checkbox.checked = defaultValue; + if (value !== undefined) { + checkbox.checked = value; + if (value !== defaultValue) { + if (typeof defaultValue === 'object') { + if (value !== defaultValue.enabled) { this.changedOptions.push({ path: path, value: value }); } + } else { + this.changedOptions.push({ path: path, value: value }); } } + } - var me = this; - checkbox.onchange = function () { - me._update(this.checked, path); - }; - - var label = this._makeLabel(path[path.length - 1], path); - this._makeEntree(path, label, checkbox); - }, - writable: true, - configurable: true - }, - _makeColorField: { - + var me = this; + checkbox.onchange = function () { + me._update(this.checked, path); + }; - /** - * make a color field with a color picker for color fields - * @param arr - * @param value - * @param path - * @private - */ - value: function _makeColorField(arr, value, path) { - var _this = this; - var defaultColor = arr[1]; - var div = document.createElement("div"); - value = value === undefined ? defaultColor : value; - - if (value !== "none") { - div.className = "vis-network-configuration colorBlock"; - div.style.backgroundColor = value; - } else { - div.className = "vis-network-configuration colorBlock none"; - } + var label = this._makeLabel(path[path.length - 1], path); + this._makeEntree(path, label, checkbox); + } + }, { + key: '_makeColorField', - value = value === undefined ? defaultColor : value; - div.onclick = function () { - _this._showColorPicker(value, div, path); - }; + /** + * make a color field with a color picker for color fields + * @param arr + * @param value + * @param path + * @private + */ + value: function _makeColorField(arr, value, path) { + var _this2 = this; - var label = this._makeLabel(path[path.length - 1], path); - this._makeEntree(path, label, div); - }, - writable: true, - configurable: true - }, - _showColorPicker: { + var defaultColor = arr[1]; + var div = document.createElement('div'); + value = value === undefined ? defaultColor : value; + if (value !== 'none') { + div.className = 'vis-network-configuration colorBlock'; + div.style.backgroundColor = value; + } else { + div.className = 'vis-network-configuration colorBlock none'; + } - /** - * used by the color buttons to call the color picker. - * @param event - * @param value - * @param div - * @param path - * @private - */ - value: function _showColorPicker(value, div, path) { - var _this = this; - var rect = div.getBoundingClientRect(); - var bodyRect = document.body.getBoundingClientRect(); - var pickerX = rect.left + rect.width + 5; - var pickerY = rect.top - bodyRect.top + rect.height * 0.5; - this.colorPicker.show(pickerX, pickerY); - this.colorPicker.setColor(value); - this.colorPicker.setCallback(function (color) { - var colorString = "rgba(" + color.r + "," + color.g + "," + color.b + "," + color.a + ")"; - div.style.backgroundColor = colorString; - _this._update(colorString, path); - }); - }, - writable: true, - configurable: true - }, - _handleObject: { + value = value === undefined ? defaultColor : value; + div.onclick = function () { + _this2._showColorPicker(value, div, path); + }; + var label = this._makeLabel(path[path.length - 1], path); + this._makeEntree(path, label, div); + } + }, { + key: '_showColorPicker', - /** - * parse an object and draw the correct entrees - * @param obj - * @param path - * @private - */ - value: function _handleObject(obj) { - var path = arguments[1] === undefined ? [] : arguments[1]; - for (var subObj in obj) { - if (obj.hasOwnProperty(subObj)) { - var item = obj[subObj]; - var newPath = this._addToPath(path, subObj); - var value = this._getValue(newPath); - - if (item instanceof Array) { - this._handleArray(item, value, newPath); - } else if (typeof item === "string") { - this._handleString(item, value, newPath); - } else if (typeof item === "boolean") { - this._makeCheckbox(item, value, newPath); - } else if (item instanceof Object) { - // collapse the physics options that are not enabled - var draw = true; - if (path.indexOf("physics") !== -1) { - if (this.actualOptions.physics.solver !== subObj) { - draw = false; - } + /** + * used by the color buttons to call the color picker. + * @param event + * @param value + * @param div + * @param path + * @private + */ + value: function _showColorPicker(value, div, path) { + var _this3 = this; + + var rect = div.getBoundingClientRect(); + var bodyRect = document.body.getBoundingClientRect(); + var pickerX = rect.left + rect.width + 5; + var pickerY = rect.top - bodyRect.top + rect.height * 0.5; + this.colorPicker.show(pickerX, pickerY); + this.colorPicker.setColor(value); + this.colorPicker.setCallback(function (color) { + var colorString = 'rgba(' + color.r + ',' + color.g + ',' + color.b + ',' + color.a + ')'; + div.style.backgroundColor = colorString; + _this3._update(colorString, path); + }); + } + }, { + key: '_handleObject', + + /** + * parse an object and draw the correct entrees + * @param obj + * @param path + * @private + */ + value: function _handleObject(obj) { + var path = arguments[1] === undefined ? [] : arguments[1]; + + for (var subObj in obj) { + if (obj.hasOwnProperty(subObj)) { + var item = obj[subObj]; + var newPath = this._addToPath(path, subObj); + var value = this._getValue(newPath); + + if (item instanceof Array) { + this._handleArray(item, value, newPath); + } else if (typeof item === 'string') { + this._handleString(item, value, newPath); + } else if (typeof item === 'boolean') { + this._makeCheckbox(item, value, newPath); + } else if (item instanceof Object) { + // collapse the physics options that are not enabled + var draw = true; + if (path.indexOf('physics') !== -1) { + if (this.actualOptions.physics.solver !== subObj) { + draw = false; } + } - if (draw === true) { - // initially collapse options with an disabled enabled option. - if (item.enabled !== undefined) { - var enabledPath = this._addToPath(newPath, "enabled"); - var enabledValue = this._getValue(enabledPath); - if (enabledValue === true) { - var label = this._makeLabel(subObj, newPath, true); - this._makeEntree(newPath, label); - this._handleObject(item, newPath); - } else { - this._makeCheckbox(item, enabledValue, newPath); - } - } else { + if (draw === true) { + // initially collapse options with an disabled enabled option. + if (item.enabled !== undefined) { + var enabledPath = this._addToPath(newPath, 'enabled'); + var enabledValue = this._getValue(enabledPath); + if (enabledValue === true) { var label = this._makeLabel(subObj, newPath, true); this._makeEntree(newPath, label); this._handleObject(item, newPath); + } else { + this._makeCheckbox(item, enabledValue, newPath); } + } else { + var label = this._makeLabel(subObj, newPath, true); + this._makeEntree(newPath, label); + this._handleObject(item, newPath); } - } else { - console.error("dont know how to handle", item, subObj, newPath); } + } else { + console.error('dont know how to handle', item, subObj, newPath); } } - }, - writable: true, - configurable: true - }, - _handleArray: { - + } + } + }, { + key: '_handleArray', - /** - * handle the array type of option - * @param optionName - * @param arr - * @param value - * @param path - * @private - */ - value: function _handleArray(arr, value, path) { - if (typeof arr[0] === "string" && arr[0] === "color") { - this._makeColorField(arr, value, path); - if (arr[1] !== value) { - this.changedOptions.push({ path: path, value: value }); - } - } else if (typeof arr[0] === "string") { - this._makeDropdown(arr, value, path); - if (arr[0] !== value) { - this.changedOptions.push({ path: path, value: value }); - } - } else if (typeof arr[0] === "number") { - this._makeRange(arr, value, path); - if (arr[0] !== value) { - this.changedOptions.push({ path: path, value: value }); - } + /** + * handle the array type of option + * @param optionName + * @param arr + * @param value + * @param path + * @private + */ + value: function _handleArray(arr, value, path) { + if (typeof arr[0] === 'string' && arr[0] === 'color') { + this._makeColorField(arr, value, path); + if (arr[1] !== value) { + this.changedOptions.push({ path: path, value: value }); + } + } else if (typeof arr[0] === 'string') { + this._makeDropdown(arr, value, path); + if (arr[0] !== value) { + this.changedOptions.push({ path: path, value: value }); + } + } else if (typeof arr[0] === 'number') { + this._makeRange(arr, value, path); + if (arr[0] !== value) { + this.changedOptions.push({ path: path, value: value }); } + } + } + }, { + key: '_handleString', - }, - writable: true, - configurable: true - }, - _handleString: { - - - /** - * handle the string type of option. - * TODO: Not sure what to do with this - * @param optionName - * @param string - * @param value - * @param path - * @private - */ - value: function _handleString(string, value, path) { - if (string === "string") {} else {} - }, - writable: true, - configurable: true - }, - _update: { - + /** + * handle the string type of option. + * TODO: Not sure what to do with this + * @param optionName + * @param string + * @param value + * @param path + * @private + */ + value: function _handleString(string, value, path) { + if (string === 'string') {} else {} + } + }, { + key: '_update', - /** - * called to update the network with the new settings. - * @param value - * @param path - * @private - */ - value: function _update(value, path) { - var options = this._constructOptions(value, path); - this.network.setOptions(options); - }, - writable: true, - configurable: true - }, - _constructOptions: { - value: function _constructOptions(value, path) { - var optionsObj = arguments[2] === undefined ? {} : arguments[2]; - var pointer = optionsObj; - for (var i = 0; i < path.length; i++) { - if (pointer[path[i]] === undefined) { - pointer[path[i]] = {}; - } - if (i !== path.length - 1) { - pointer = pointer[path[i]]; - } else { - pointer[path[i]] = value; - } - } - return optionsObj; - }, - writable: true, - configurable: true - }, - _printOptions: { - value: function _printOptions() { - var options = {}; - for (var i = 0; i < this.changedOptions.length; i++) { - this._constructOptions(this.changedOptions[i].value, this.changedOptions[i].path, options); + /** + * called to update the network with the new settings. + * @param value + * @param path + * @private + */ + value: function _update(value, path) { + var options = this._constructOptions(value, path); + this.network.setOptions(options); + } + }, { + key: '_constructOptions', + value: function _constructOptions(value, path) { + var optionsObj = arguments[2] === undefined ? {} : arguments[2]; + + var pointer = optionsObj; + for (var i = 0; i < path.length; i++) { + if (pointer[path[i]] === undefined) { + pointer[path[i]] = {}; + } + if (i !== path.length - 1) { + pointer = pointer[path[i]]; + } else { + pointer[path[i]] = value; } - this.optionsContainer.innerHTML = "
var options = " + JSON.stringify(options, null, 2) + "
"; - }, - writable: true, - configurable: true + } + return optionsObj; + } + }, { + key: '_printOptions', + value: function _printOptions() { + var options = {}; + for (var i = 0; i < this.changedOptions.length; i++) { + this._constructOptions(this.changedOptions[i].value, this.changedOptions[i].path, options); + } + this.optionsContainer.innerHTML = '
var options = ' + JSON.stringify(options, null, 2) + '
'; } - }); + }]); return ConfigurationSystem; })(); - module.exports = ConfigurationSystem; + exports['default'] = ConfigurationSystem; + module.exports = exports['default']; + //this._makeLabel(optionName, path); //console.log('string', string, value, path); /***/ }, -/* 63 */ +/* 62 */ /***/ function(module, exports, __webpack_require__) { - /* WEBPACK VAR INJECTION */(function(module) {//! moment.js - //! version : 2.10.2 - //! authors : Tim Wood, Iskren Chernev, Moment.js contributors - //! license : MIT - //! momentjs.com + /** + * Canvas shapes used by Network + */ + 'use strict'; - (function (global, factory) { - true ? module.exports = factory() : - typeof define === 'function' && define.amd ? define(factory) : - global.moment = factory() - }(this, function () { 'use strict'; + if (typeof CanvasRenderingContext2D !== 'undefined') { - var hookCallback; + /** + * Draw a circle shape + */ + CanvasRenderingContext2D.prototype.circle = function (x, y, r) { + this.beginPath(); + this.arc(x, y, r, 0, 2 * Math.PI, false); + }; - function utils_hooks__hooks () { - return hookCallback.apply(null, arguments); - } + /** + * 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); + }; - // This is done to register the method called with moment() - // without creating circular dependencies. - function setHookCallback (callback) { - hookCallback = callback; - } + /** + * 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(); - function defaultParsingFlags() { - // We need to deep clone this object. - return { - empty : false, - unusedTokens : [], - unusedInput : [], - overflow : -2, - charsLeftOver : 0, - nullInput : false, - invalidMonth : null, - invalidFormat : false, - userInvalidated : false, - iso : false - }; - } + // the change in radius and the offset is here to center the shape + r *= 1.15; + y += 0.275 * r; - function isArray(input) { - return Object.prototype.toString.call(input) === '[object Array]'; - } + 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 - function isDate(input) { - return Object.prototype.toString.call(input) === '[object Date]' || input instanceof Date; - } + 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(); + }; - function map(arr, fn) { - var res = [], i; - for (i = 0; i < arr.length; ++i) { - res.push(fn(arr[i], i)); - } - return res; - } + /** + * 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(); - function hasOwnProp(a, b) { - return Object.prototype.hasOwnProperty.call(a, b); - } + // the change in radius and the offset is here to center the shape + r *= 1.15; + y -= 0.275 * r; - function extend(a, b) { - for (var i in b) { - if (hasOwnProp(b, i)) { - a[i] = b[i]; - } - } + 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 (hasOwnProp(b, 'toString')) { - a.toString = b.toString; - } + 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 (hasOwnProp(b, 'valueOf')) { - a.valueOf = b.valueOf; - } + /** + * 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(); - return a; - } + // the change in radius and the offset is here to center the shape + r *= 0.82; + y += 0.1 * r; - function create_utc__createUTC (input, format, locale, strict) { - return createLocalOrUTC(input, format, locale, strict, true).utc(); + 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)); } - function valid__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; + this.closePath(); + }; - if (m._strict) { - m._isValid = m._isValid && - m._pf.charsLeftOver === 0 && - m._pf.unusedTokens.length === 0 && - m._pf.bigHour === undefined; - } - } - return m._isValid; - } + /** + * Draw a Diamond 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.diamond = function (x, y, r) { + // http://www.html5canvastutorials.com/labs/html5-canvas-star-spinner/ + this.beginPath(); - function valid__createInvalid (flags) { - var m = create_utc__createUTC(NaN); - if (flags != null) { - extend(m._pf, flags); - } - else { - m._pf.userInvalidated = true; - } + this.lineTo(x, y + r); + this.lineTo(x + r, y); + this.lineTo(x, y - r); + this.lineTo(x - r, y); - return m; - } + this.closePath(); + }; - var momentProperties = utils_hooks__hooks.momentProperties = []; + /** + * 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 = 0.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 = 0.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 + } + +/***/ }, +/* 63 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var keycharm = __webpack_require__(81); + var Emitter = __webpack_require__(42); + var Hammer = __webpack_require__(41); + var util = __webpack_require__(1); + + /** + * 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; + + this.dom = { + container: container + }; + + 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(); + } + }); + + if (this.keycharm !== undefined) { + this.keycharm.destroy(); + } + this.keycharm = keycharm(); + + // 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) + }; + + /** + * Activate the element + * Overlay is hidden, element is decorated with a blue shadow border + */ + Activator.prototype.activate = function () { + // we allow only one active activator at a time + if (Activator.current) { + Activator.current.deactivate(); + } + 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); + + this.emit('change'); + this.emit('deactivate'); + }; + + /** + * Handle a tap event: activate the container + * @param event + * @private + */ + Activator.prototype._onTapOverlay = function (event) { + // activate the container + this.activate(); + event.stopPropagation(); + }; + + /** + * Test whether the element has the requested parent element somewhere in + * its chain of parent nodes. + * @param {HTMLElement} element + * @param {HTMLElement} parent + * @returns {boolean} Returns true when the parent is found somewhere in the + * chain of parent nodes. + * @private + */ + function _hasParent(element, parent) { + while (element) { + if (element === parent) { + return true; + } + element = element.parentNode; + } + return false; + } + + module.exports = Activator; + +/***/ }, +/* 64 */ +/***/ function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(module) {//! moment.js + //! version : 2.10.2 + //! authors : Tim Wood, Iskren Chernev, Moment.js contributors + //! license : MIT + //! momentjs.com + + (function (global, factory) { + true ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + global.moment = factory() + }(this, function () { 'use strict'; + + var hookCallback; + + function utils_hooks__hooks () { + return hookCallback.apply(null, arguments); + } + + // This is done to register the method called with moment() + // without creating circular dependencies. + function setHookCallback (callback) { + hookCallback = callback; + } + + function defaultParsingFlags() { + // We need to deep clone this object. + return { + empty : false, + unusedTokens : [], + unusedInput : [], + overflow : -2, + charsLeftOver : 0, + nullInput : false, + invalidMonth : null, + invalidFormat : false, + userInvalidated : false, + iso : false + }; + } + + function isArray(input) { + return Object.prototype.toString.call(input) === '[object Array]'; + } + + function isDate(input) { + return Object.prototype.toString.call(input) === '[object Date]' || input instanceof Date; + } + + function map(arr, fn) { + var res = [], i; + for (i = 0; i < arr.length; ++i) { + res.push(fn(arr[i], i)); + } + return res; + } + + function hasOwnProp(a, b) { + return Object.prototype.hasOwnProperty.call(a, b); + } + + function extend(a, b) { + for (var i in b) { + if (hasOwnProp(b, i)) { + a[i] = b[i]; + } + } + + if (hasOwnProp(b, 'toString')) { + a.toString = b.toString; + } + + if (hasOwnProp(b, 'valueOf')) { + a.valueOf = b.valueOf; + } + + return a; + } + + function create_utc__createUTC (input, format, locale, strict) { + return createLocalOrUTC(input, format, locale, strict, true).utc(); + } + + function valid__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; + } + + function valid__createInvalid (flags) { + var m = create_utc__createUTC(NaN); + if (flags != null) { + extend(m._pf, flags); + } + else { + m._pf.userInvalidated = true; + } + + return m; + } + + var momentProperties = utils_hooks__hooks.momentProperties = []; function copyConfig(to, from) { var i, prop, val; @@ -27429,3771 +28016,4731 @@ return /******/ (function(modules) { // webpackBootstrap return ((input + '').toLowerCase().charAt(0) === 'p'); } - var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i; - function localeMeridiem (hours, minutes, isLower) { - if (hours > 11) { - return isLower ? 'pm' : 'PM'; - } else { - return isLower ? 'am' : 'AM'; + var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i; + function localeMeridiem (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'pm' : 'PM'; + } else { + return isLower ? 'am' : 'AM'; + } + } + + + // MOMENTS + + // 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. + var getSetHour = makeGetSet('Hours', true); + + addFormatToken('m', ['mm', 2], 0, 'minute'); + + // ALIASES + + addUnitAlias('minute', 'm'); + + // PARSING + + addRegexToken('m', match1to2); + addRegexToken('mm', match1to2, match2); + addParseToken(['m', 'mm'], MINUTE); + + // MOMENTS + + var getSetMinute = makeGetSet('Minutes', false); + + addFormatToken('s', ['ss', 2], 0, 'second'); + + // ALIASES + + addUnitAlias('second', 's'); + + // PARSING + + addRegexToken('s', match1to2); + addRegexToken('ss', match1to2, match2); + addParseToken(['s', 'ss'], SECOND); + + // MOMENTS + + var getSetSecond = makeGetSet('Seconds', false); + + addFormatToken('S', 0, 0, function () { + return ~~(this.millisecond() / 100); + }); + + addFormatToken(0, ['SS', 2], 0, function () { + return ~~(this.millisecond() / 10); + }); + + function millisecond__milliseconds (token) { + addFormatToken(0, [token, 3], 0, 'millisecond'); + } + + millisecond__milliseconds('SSS'); + millisecond__milliseconds('SSSS'); + + // ALIASES + + addUnitAlias('millisecond', 'ms'); + + // PARSING + + addRegexToken('S', match1to3, match1); + addRegexToken('SS', match1to3, match2); + addRegexToken('SSS', match1to3, match3); + addRegexToken('SSSS', matchUnsigned); + addParseToken(['S', 'SS', 'SSS', 'SSSS'], function (input, array) { + array[MILLISECOND] = toInt(('0.' + input) * 1000); + }); + + // MOMENTS + + var getSetMillisecond = makeGetSet('Milliseconds', false); + + addFormatToken('z', 0, 0, 'zoneAbbr'); + addFormatToken('zz', 0, 0, 'zoneName'); + + // MOMENTS + + function getZoneAbbr () { + return this._isUTC ? 'UTC' : ''; + } + + function getZoneName () { + return this._isUTC ? 'Coordinated Universal Time' : ''; + } + + var momentPrototype__proto = Moment.prototype; + + momentPrototype__proto.add = add_subtract__add; + momentPrototype__proto.calendar = moment_calendar__calendar; + momentPrototype__proto.clone = clone; + momentPrototype__proto.diff = diff; + momentPrototype__proto.endOf = endOf; + momentPrototype__proto.format = format; + momentPrototype__proto.from = from; + momentPrototype__proto.fromNow = fromNow; + momentPrototype__proto.get = getSet; + momentPrototype__proto.invalidAt = invalidAt; + momentPrototype__proto.isAfter = isAfter; + momentPrototype__proto.isBefore = isBefore; + momentPrototype__proto.isBetween = isBetween; + momentPrototype__proto.isSame = isSame; + momentPrototype__proto.isValid = moment_valid__isValid; + momentPrototype__proto.lang = lang; + momentPrototype__proto.locale = locale; + momentPrototype__proto.localeData = localeData; + momentPrototype__proto.max = prototypeMax; + momentPrototype__proto.min = prototypeMin; + momentPrototype__proto.parsingFlags = parsingFlags; + momentPrototype__proto.set = getSet; + momentPrototype__proto.startOf = startOf; + momentPrototype__proto.subtract = add_subtract__subtract; + momentPrototype__proto.toArray = toArray; + momentPrototype__proto.toDate = toDate; + momentPrototype__proto.toISOString = moment_format__toISOString; + momentPrototype__proto.toJSON = moment_format__toISOString; + momentPrototype__proto.toString = toString; + momentPrototype__proto.unix = unix; + momentPrototype__proto.valueOf = to_type__valueOf; + + // Year + momentPrototype__proto.year = getSetYear; + momentPrototype__proto.isLeapYear = getIsLeapYear; + + // Week Year + momentPrototype__proto.weekYear = getSetWeekYear; + momentPrototype__proto.isoWeekYear = getSetISOWeekYear; + + // Quarter + momentPrototype__proto.quarter = momentPrototype__proto.quarters = getSetQuarter; + + // Month + momentPrototype__proto.month = getSetMonth; + momentPrototype__proto.daysInMonth = getDaysInMonth; + + // Week + momentPrototype__proto.week = momentPrototype__proto.weeks = getSetWeek; + momentPrototype__proto.isoWeek = momentPrototype__proto.isoWeeks = getSetISOWeek; + momentPrototype__proto.weeksInYear = getWeeksInYear; + momentPrototype__proto.isoWeeksInYear = getISOWeeksInYear; + + // Day + momentPrototype__proto.date = getSetDayOfMonth; + momentPrototype__proto.day = momentPrototype__proto.days = getSetDayOfWeek; + momentPrototype__proto.weekday = getSetLocaleDayOfWeek; + momentPrototype__proto.isoWeekday = getSetISODayOfWeek; + momentPrototype__proto.dayOfYear = getSetDayOfYear; + + // Hour + momentPrototype__proto.hour = momentPrototype__proto.hours = getSetHour; + + // Minute + momentPrototype__proto.minute = momentPrototype__proto.minutes = getSetMinute; + + // Second + momentPrototype__proto.second = momentPrototype__proto.seconds = getSetSecond; + + // Millisecond + momentPrototype__proto.millisecond = momentPrototype__proto.milliseconds = getSetMillisecond; + + // Offset + momentPrototype__proto.utcOffset = getSetOffset; + momentPrototype__proto.utc = setOffsetToUTC; + momentPrototype__proto.local = setOffsetToLocal; + momentPrototype__proto.parseZone = setOffsetToParsedOffset; + momentPrototype__proto.hasAlignedHourOffset = hasAlignedHourOffset; + momentPrototype__proto.isDST = isDaylightSavingTime; + momentPrototype__proto.isDSTShifted = isDaylightSavingTimeShifted; + momentPrototype__proto.isLocal = isLocal; + momentPrototype__proto.isUtcOffset = isUtcOffset; + momentPrototype__proto.isUtc = isUtc; + momentPrototype__proto.isUTC = isUtc; + + // Timezone + momentPrototype__proto.zoneAbbr = getZoneAbbr; + momentPrototype__proto.zoneName = getZoneName; + + // Deprecations + momentPrototype__proto.dates = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth); + momentPrototype__proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth); + momentPrototype__proto.years = deprecate('years accessor is deprecated. Use year instead', getSetYear); + momentPrototype__proto.zone = deprecate('moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779', getSetZone); + + var momentPrototype = momentPrototype__proto; + + function moment__createUnix (input) { + return local__createLocal(input * 1000); + } + + function moment__createInZone () { + return local__createLocal.apply(null, arguments).parseZone(); + } + + var defaultCalendar = { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }; + + function locale_calendar__calendar (key, mom, now) { + var output = this._calendar[key]; + return typeof output === 'function' ? output.call(mom, now) : output; + } + + var defaultLongDateFormat = { + 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' + }; + + function longDateFormat (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; } + var defaultInvalidDate = 'Invalid date'; - // MOMENTS + function invalidDate () { + return this._invalidDate; + } - // 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. - var getSetHour = makeGetSet('Hours', true); + var defaultOrdinal = '%d'; + var defaultOrdinalParse = /\d{1,2}/; - addFormatToken('m', ['mm', 2], 0, 'minute'); + function ordinal (number) { + return this._ordinal.replace('%d', number); + } - // ALIASES + function preParsePostFormat (string) { + return string; + } - addUnitAlias('minute', 'm'); + var defaultRelativeTime = { + 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' + }; - // PARSING + function relative__relativeTime (number, withoutSuffix, string, isFuture) { + var output = this._relativeTime[string]; + return (typeof output === 'function') ? + output(number, withoutSuffix, string, isFuture) : + output.replace(/%d/i, number); + } - addRegexToken('m', match1to2); - addRegexToken('mm', match1to2, match2); - addParseToken(['m', 'mm'], MINUTE); + function pastFuture (diff, output) { + var format = this._relativeTime[diff > 0 ? 'future' : 'past']; + return typeof format === 'function' ? format(output) : format.replace(/%s/i, output); + } - // MOMENTS + function locale_set__set (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); + } - var getSetMinute = makeGetSet('Minutes', false); + var prototype__proto = Locale.prototype; - addFormatToken('s', ['ss', 2], 0, 'second'); + prototype__proto._calendar = defaultCalendar; + prototype__proto.calendar = locale_calendar__calendar; + prototype__proto._longDateFormat = defaultLongDateFormat; + prototype__proto.longDateFormat = longDateFormat; + prototype__proto._invalidDate = defaultInvalidDate; + prototype__proto.invalidDate = invalidDate; + prototype__proto._ordinal = defaultOrdinal; + prototype__proto.ordinal = ordinal; + prototype__proto._ordinalParse = defaultOrdinalParse; + prototype__proto.preparse = preParsePostFormat; + prototype__proto.postformat = preParsePostFormat; + prototype__proto._relativeTime = defaultRelativeTime; + prototype__proto.relativeTime = relative__relativeTime; + prototype__proto.pastFuture = pastFuture; + prototype__proto.set = locale_set__set; - // ALIASES + // Month + prototype__proto.months = localeMonths; + prototype__proto._months = defaultLocaleMonths; + prototype__proto.monthsShort = localeMonthsShort; + prototype__proto._monthsShort = defaultLocaleMonthsShort; + prototype__proto.monthsParse = localeMonthsParse; - addUnitAlias('second', 's'); + // Week + prototype__proto.week = localeWeek; + prototype__proto._week = defaultLocaleWeek; + prototype__proto.firstDayOfYear = localeFirstDayOfYear; + prototype__proto.firstDayOfWeek = localeFirstDayOfWeek; - // PARSING + // Day of Week + prototype__proto.weekdays = localeWeekdays; + prototype__proto._weekdays = defaultLocaleWeekdays; + prototype__proto.weekdaysMin = localeWeekdaysMin; + prototype__proto._weekdaysMin = defaultLocaleWeekdaysMin; + prototype__proto.weekdaysShort = localeWeekdaysShort; + prototype__proto._weekdaysShort = defaultLocaleWeekdaysShort; + prototype__proto.weekdaysParse = localeWeekdaysParse; - addRegexToken('s', match1to2); - addRegexToken('ss', match1to2, match2); - addParseToken(['s', 'ss'], SECOND); + // Hours + prototype__proto.isPM = localeIsPM; + prototype__proto._meridiemParse = defaultLocaleMeridiemParse; + prototype__proto.meridiem = localeMeridiem; - // MOMENTS + function lists__get (format, index, field, setter) { + var locale = locale_locales__getLocale(); + var utc = create_utc__createUTC().set(setter, index); + return locale[field](utc, format); + } - var getSetSecond = makeGetSet('Seconds', false); + function list (format, index, field, count, setter) { + if (typeof format === 'number') { + index = format; + format = undefined; + } - addFormatToken('S', 0, 0, function () { - return ~~(this.millisecond() / 100); - }); + format = format || ''; - addFormatToken(0, ['SS', 2], 0, function () { - return ~~(this.millisecond() / 10); - }); + if (index != null) { + return lists__get(format, index, field, setter); + } - function millisecond__milliseconds (token) { - addFormatToken(0, [token, 3], 0, 'millisecond'); + var i; + var out = []; + for (i = 0; i < count; i++) { + out[i] = lists__get(format, i, field, setter); + } + return out; } - millisecond__milliseconds('SSS'); - millisecond__milliseconds('SSSS'); - - // ALIASES - - addUnitAlias('millisecond', 'ms'); - - // PARSING + function lists__listMonths (format, index) { + return list(format, index, 'months', 12, 'month'); + } - addRegexToken('S', match1to3, match1); - addRegexToken('SS', match1to3, match2); - addRegexToken('SSS', match1to3, match3); - addRegexToken('SSSS', matchUnsigned); - addParseToken(['S', 'SS', 'SSS', 'SSSS'], function (input, array) { - array[MILLISECOND] = toInt(('0.' + input) * 1000); - }); + function lists__listMonthsShort (format, index) { + return list(format, index, 'monthsShort', 12, 'month'); + } - // MOMENTS + function lists__listWeekdays (format, index) { + return list(format, index, 'weekdays', 7, 'day'); + } - var getSetMillisecond = makeGetSet('Milliseconds', false); + function lists__listWeekdaysShort (format, index) { + return list(format, index, 'weekdaysShort', 7, 'day'); + } - addFormatToken('z', 0, 0, 'zoneAbbr'); - addFormatToken('zz', 0, 0, 'zoneName'); + function lists__listWeekdaysMin (format, index) { + return list(format, index, 'weekdaysMin', 7, 'day'); + } - // MOMENTS + locale_locales__getSetGlobalLocale('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; + } + }); - function getZoneAbbr () { - return this._isUTC ? 'UTC' : ''; - } + // Side effect imports + utils_hooks__hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', locale_locales__getSetGlobalLocale); + utils_hooks__hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', locale_locales__getLocale); - function getZoneName () { - return this._isUTC ? 'Coordinated Universal Time' : ''; - } + var mathAbs = Math.abs; - var momentPrototype__proto = Moment.prototype; + function duration_abs__abs () { + var data = this._data; - momentPrototype__proto.add = add_subtract__add; - momentPrototype__proto.calendar = moment_calendar__calendar; - momentPrototype__proto.clone = clone; - momentPrototype__proto.diff = diff; - momentPrototype__proto.endOf = endOf; - momentPrototype__proto.format = format; - momentPrototype__proto.from = from; - momentPrototype__proto.fromNow = fromNow; - momentPrototype__proto.get = getSet; - momentPrototype__proto.invalidAt = invalidAt; - momentPrototype__proto.isAfter = isAfter; - momentPrototype__proto.isBefore = isBefore; - momentPrototype__proto.isBetween = isBetween; - momentPrototype__proto.isSame = isSame; - momentPrototype__proto.isValid = moment_valid__isValid; - momentPrototype__proto.lang = lang; - momentPrototype__proto.locale = locale; - momentPrototype__proto.localeData = localeData; - momentPrototype__proto.max = prototypeMax; - momentPrototype__proto.min = prototypeMin; - momentPrototype__proto.parsingFlags = parsingFlags; - momentPrototype__proto.set = getSet; - momentPrototype__proto.startOf = startOf; - momentPrototype__proto.subtract = add_subtract__subtract; - momentPrototype__proto.toArray = toArray; - momentPrototype__proto.toDate = toDate; - momentPrototype__proto.toISOString = moment_format__toISOString; - momentPrototype__proto.toJSON = moment_format__toISOString; - momentPrototype__proto.toString = toString; - momentPrototype__proto.unix = unix; - momentPrototype__proto.valueOf = to_type__valueOf; + this._milliseconds = mathAbs(this._milliseconds); + this._days = mathAbs(this._days); + this._months = mathAbs(this._months); - // Year - momentPrototype__proto.year = getSetYear; - momentPrototype__proto.isLeapYear = getIsLeapYear; + data.milliseconds = mathAbs(data.milliseconds); + data.seconds = mathAbs(data.seconds); + data.minutes = mathAbs(data.minutes); + data.hours = mathAbs(data.hours); + data.months = mathAbs(data.months); + data.years = mathAbs(data.years); - // Week Year - momentPrototype__proto.weekYear = getSetWeekYear; - momentPrototype__proto.isoWeekYear = getSetISOWeekYear; + return this; + } - // Quarter - momentPrototype__proto.quarter = momentPrototype__proto.quarters = getSetQuarter; + function duration_add_subtract__addSubtract (duration, input, value, direction) { + var other = create__createDuration(input, value); - // Month - momentPrototype__proto.month = getSetMonth; - momentPrototype__proto.daysInMonth = getDaysInMonth; + duration._milliseconds += direction * other._milliseconds; + duration._days += direction * other._days; + duration._months += direction * other._months; - // Week - momentPrototype__proto.week = momentPrototype__proto.weeks = getSetWeek; - momentPrototype__proto.isoWeek = momentPrototype__proto.isoWeeks = getSetISOWeek; - momentPrototype__proto.weeksInYear = getWeeksInYear; - momentPrototype__proto.isoWeeksInYear = getISOWeeksInYear; + return duration._bubble(); + } - // Day - momentPrototype__proto.date = getSetDayOfMonth; - momentPrototype__proto.day = momentPrototype__proto.days = getSetDayOfWeek; - momentPrototype__proto.weekday = getSetLocaleDayOfWeek; - momentPrototype__proto.isoWeekday = getSetISODayOfWeek; - momentPrototype__proto.dayOfYear = getSetDayOfYear; + // supports only 2.0-style add(1, 's') or add(duration) + function duration_add_subtract__add (input, value) { + return duration_add_subtract__addSubtract(this, input, value, 1); + } - // Hour - momentPrototype__proto.hour = momentPrototype__proto.hours = getSetHour; + // supports only 2.0-style subtract(1, 's') or subtract(duration) + function duration_add_subtract__subtract (input, value) { + return duration_add_subtract__addSubtract(this, input, value, -1); + } - // Minute - momentPrototype__proto.minute = momentPrototype__proto.minutes = getSetMinute; + function bubble () { + var milliseconds = this._milliseconds; + var days = this._days; + var months = this._months; + var data = this._data; + var seconds, minutes, hours, years = 0; - // Second - momentPrototype__proto.second = momentPrototype__proto.seconds = getSetSecond; + // The following code bubbles up values, see the tests for + // examples of what that means. + data.milliseconds = milliseconds % 1000; - // Millisecond - momentPrototype__proto.millisecond = momentPrototype__proto.milliseconds = getSetMillisecond; + seconds = absFloor(milliseconds / 1000); + data.seconds = seconds % 60; - // Offset - momentPrototype__proto.utcOffset = getSetOffset; - momentPrototype__proto.utc = setOffsetToUTC; - momentPrototype__proto.local = setOffsetToLocal; - momentPrototype__proto.parseZone = setOffsetToParsedOffset; - momentPrototype__proto.hasAlignedHourOffset = hasAlignedHourOffset; - momentPrototype__proto.isDST = isDaylightSavingTime; - momentPrototype__proto.isDSTShifted = isDaylightSavingTimeShifted; - momentPrototype__proto.isLocal = isLocal; - momentPrototype__proto.isUtcOffset = isUtcOffset; - momentPrototype__proto.isUtc = isUtc; - momentPrototype__proto.isUTC = isUtc; + minutes = absFloor(seconds / 60); + data.minutes = minutes % 60; - // Timezone - momentPrototype__proto.zoneAbbr = getZoneAbbr; - momentPrototype__proto.zoneName = getZoneName; + hours = absFloor(minutes / 60); + data.hours = hours % 24; - // Deprecations - momentPrototype__proto.dates = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth); - momentPrototype__proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth); - momentPrototype__proto.years = deprecate('years accessor is deprecated. Use year instead', getSetYear); - momentPrototype__proto.zone = deprecate('moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779', getSetZone); + days += absFloor(hours / 24); - var momentPrototype = momentPrototype__proto; + // Accurately convert days to years, assume start from year 0. + years = absFloor(daysToYears(days)); + days -= absFloor(yearsToDays(years)); - function moment__createUnix (input) { - return local__createLocal(input * 1000); - } + // 30 days to a month + // TODO (iskren): Use anchor date (like 1st Jan) to compute this. + months += absFloor(days / 30); + days %= 30; - function moment__createInZone () { - return local__createLocal.apply(null, arguments).parseZone(); + // 12 months -> 1 year + years += absFloor(months / 12); + months %= 12; + + data.days = days; + data.months = months; + data.years = years; + + return this; } - var defaultCalendar = { - sameDay : '[Today at] LT', - nextDay : '[Tomorrow at] LT', - nextWeek : 'dddd [at] LT', - lastDay : '[Yesterday at] LT', - lastWeek : '[Last] dddd [at] LT', - sameElse : 'L' - }; + function daysToYears (days) { + // 400 years have 146097 days (taking into account leap year rules) + return days * 400 / 146097; + } - function locale_calendar__calendar (key, mom, now) { - var output = this._calendar[key]; - return typeof output === 'function' ? output.call(mom, now) : output; + function yearsToDays (years) { + // years * 365 + absFloor(years / 4) - + // absFloor(years / 100) + absFloor(years / 400); + return years * 146097 / 400; } - var defaultLongDateFormat = { - 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' - }; + function as (units) { + var days; + var months; + var milliseconds = this._milliseconds; - function longDateFormat (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; + units = normalizeUnits(units); + + if (units === 'month' || units === 'year') { + days = this._days + 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 + milliseconds / 6048e5; + case 'day' : return days + milliseconds / 864e5; + case 'hour' : return days * 24 + milliseconds / 36e5; + case 'minute' : return days * 24 * 60 + milliseconds / 6e4; + case 'second' : return days * 24 * 60 * 60 + milliseconds / 1000; + // Math.floor prevents floating point math errors here + case 'millisecond': return Math.floor(days * 24 * 60 * 60 * 1000) + milliseconds; + default: throw new Error('Unknown unit ' + units); + } } - return output; } - var defaultInvalidDate = 'Invalid date'; + // TODO: Use this.as('ms')? + function duration_as__valueOf () { + return ( + this._milliseconds + + this._days * 864e5 + + (this._months % 12) * 2592e6 + + toInt(this._months / 12) * 31536e6 + ); + } - function invalidDate () { - return this._invalidDate; + function makeAs (alias) { + return function () { + return this.as(alias); + }; } - var defaultOrdinal = '%d'; - var defaultOrdinalParse = /\d{1,2}/; + var asMilliseconds = makeAs('ms'); + var asSeconds = makeAs('s'); + var asMinutes = makeAs('m'); + var asHours = makeAs('h'); + var asDays = makeAs('d'); + var asWeeks = makeAs('w'); + var asMonths = makeAs('M'); + var asYears = makeAs('y'); - function ordinal (number) { - return this._ordinal.replace('%d', number); + function duration_get__get (units) { + units = normalizeUnits(units); + return this[units + 's'](); } - function preParsePostFormat (string) { - return string; + function makeGetter(name) { + return function () { + return this._data[name]; + }; } - var defaultRelativeTime = { - 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' + var duration_get__milliseconds = makeGetter('milliseconds'); + var seconds = makeGetter('seconds'); + var minutes = makeGetter('minutes'); + var hours = makeGetter('hours'); + var days = makeGetter('days'); + var months = makeGetter('months'); + var years = makeGetter('years'); + + function weeks () { + return absFloor(this.days() / 7); + } + + var round = Math.round; + var thresholds = { + 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 }; - function relative__relativeTime (number, withoutSuffix, string, isFuture) { - var output = this._relativeTime[string]; - return (typeof output === 'function') ? - output(number, withoutSuffix, string, isFuture) : - output.replace(/%d/i, number); + // 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); + } + + function duration_humanize__relativeTime (posNegDuration, withoutSuffix, locale) { + var duration = create__createDuration(posNegDuration).abs(); + var seconds = round(duration.as('s')); + var minutes = round(duration.as('m')); + var hours = round(duration.as('h')); + var days = round(duration.as('d')); + var months = round(duration.as('M')); + var years = round(duration.as('y')); + + var a = seconds < thresholds.s && ['s', seconds] || + minutes === 1 && ['m'] || + minutes < thresholds.m && ['mm', minutes] || + hours === 1 && ['h'] || + hours < thresholds.h && ['hh', hours] || + days === 1 && ['d'] || + days < thresholds.d && ['dd', days] || + months === 1 && ['M'] || + months < thresholds.M && ['MM', months] || + years === 1 && ['y'] || ['yy', years]; + + a[2] = withoutSuffix; + a[3] = +posNegDuration > 0; + a[4] = locale; + return substituteTimeAgo.apply(null, a); } - function pastFuture (diff, output) { - var format = this._relativeTime[diff > 0 ? 'future' : 'past']; - return typeof format === 'function' ? format(output) : format.replace(/%s/i, output); + // This function allows you to set a threshold for relative time strings + function duration_humanize__getSetRelativeTimeThreshold (threshold, limit) { + if (thresholds[threshold] === undefined) { + return false; + } + if (limit === undefined) { + return thresholds[threshold]; + } + thresholds[threshold] = limit; + return true; } - function locale_set__set (config) { - var prop, i; - for (i in config) { - prop = config[i]; - if (typeof prop === 'function') { - this[i] = prop; - } else { - this['_' + i] = prop; - } + function humanize (withSuffix) { + var locale = this.localeData(); + var output = duration_humanize__relativeTime(this, !withSuffix, locale); + + if (withSuffix) { + output = locale.pastFuture(+this, output); } - // 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 locale.postformat(output); } - var prototype__proto = Locale.prototype; + var iso_string__abs = Math.abs; - prototype__proto._calendar = defaultCalendar; - prototype__proto.calendar = locale_calendar__calendar; - prototype__proto._longDateFormat = defaultLongDateFormat; - prototype__proto.longDateFormat = longDateFormat; - prototype__proto._invalidDate = defaultInvalidDate; - prototype__proto.invalidDate = invalidDate; - prototype__proto._ordinal = defaultOrdinal; - prototype__proto.ordinal = ordinal; - prototype__proto._ordinalParse = defaultOrdinalParse; - prototype__proto.preparse = preParsePostFormat; - prototype__proto.postformat = preParsePostFormat; - prototype__proto._relativeTime = defaultRelativeTime; - prototype__proto.relativeTime = relative__relativeTime; - prototype__proto.pastFuture = pastFuture; - prototype__proto.set = locale_set__set; + function iso_string__toISOString() { + // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js + var Y = iso_string__abs(this.years()); + var M = iso_string__abs(this.months()); + var D = iso_string__abs(this.days()); + var h = iso_string__abs(this.hours()); + var m = iso_string__abs(this.minutes()); + var s = iso_string__abs(this.seconds() + this.milliseconds() / 1000); + var total = this.asSeconds(); - // Month - prototype__proto.months = localeMonths; - prototype__proto._months = defaultLocaleMonths; - prototype__proto.monthsShort = localeMonthsShort; - prototype__proto._monthsShort = defaultLocaleMonthsShort; - prototype__proto.monthsParse = localeMonthsParse; + if (!total) { + // this is the same as C#'s (Noda) and python (isodate)... + // but not other JS (goog.date) + return 'P0D'; + } - // Week - prototype__proto.week = localeWeek; - prototype__proto._week = defaultLocaleWeek; - prototype__proto.firstDayOfYear = localeFirstDayOfYear; - prototype__proto.firstDayOfWeek = localeFirstDayOfWeek; + return (total < 0 ? '-' : '') + + 'P' + + (Y ? Y + 'Y' : '') + + (M ? M + 'M' : '') + + (D ? D + 'D' : '') + + ((h || m || s) ? 'T' : '') + + (h ? h + 'H' : '') + + (m ? m + 'M' : '') + + (s ? s + 'S' : ''); + } - // Day of Week - prototype__proto.weekdays = localeWeekdays; - prototype__proto._weekdays = defaultLocaleWeekdays; - prototype__proto.weekdaysMin = localeWeekdaysMin; - prototype__proto._weekdaysMin = defaultLocaleWeekdaysMin; - prototype__proto.weekdaysShort = localeWeekdaysShort; - prototype__proto._weekdaysShort = defaultLocaleWeekdaysShort; - prototype__proto.weekdaysParse = localeWeekdaysParse; + var duration_prototype__proto = Duration.prototype; - // Hours - prototype__proto.isPM = localeIsPM; - prototype__proto._meridiemParse = defaultLocaleMeridiemParse; - prototype__proto.meridiem = localeMeridiem; + duration_prototype__proto.abs = duration_abs__abs; + duration_prototype__proto.add = duration_add_subtract__add; + duration_prototype__proto.subtract = duration_add_subtract__subtract; + duration_prototype__proto.as = as; + duration_prototype__proto.asMilliseconds = asMilliseconds; + duration_prototype__proto.asSeconds = asSeconds; + duration_prototype__proto.asMinutes = asMinutes; + duration_prototype__proto.asHours = asHours; + duration_prototype__proto.asDays = asDays; + duration_prototype__proto.asWeeks = asWeeks; + duration_prototype__proto.asMonths = asMonths; + duration_prototype__proto.asYears = asYears; + duration_prototype__proto.valueOf = duration_as__valueOf; + duration_prototype__proto._bubble = bubble; + duration_prototype__proto.get = duration_get__get; + duration_prototype__proto.milliseconds = duration_get__milliseconds; + duration_prototype__proto.seconds = seconds; + duration_prototype__proto.minutes = minutes; + duration_prototype__proto.hours = hours; + duration_prototype__proto.days = days; + duration_prototype__proto.weeks = weeks; + duration_prototype__proto.months = months; + duration_prototype__proto.years = years; + duration_prototype__proto.humanize = humanize; + duration_prototype__proto.toISOString = iso_string__toISOString; + duration_prototype__proto.toString = iso_string__toISOString; + duration_prototype__proto.toJSON = iso_string__toISOString; + duration_prototype__proto.locale = locale; + duration_prototype__proto.localeData = localeData; - function lists__get (format, index, field, setter) { - var locale = locale_locales__getLocale(); - var utc = create_utc__createUTC().set(setter, index); - return locale[field](utc, format); - } + // Deprecations + duration_prototype__proto.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', iso_string__toISOString); + duration_prototype__proto.lang = lang; - function list (format, index, field, count, setter) { - if (typeof format === 'number') { - index = format; - format = undefined; - } + // Side effect imports - format = format || ''; + addFormatToken('X', 0, 0, 'unix'); + addFormatToken('x', 0, 0, 'valueOf'); - if (index != null) { - return lists__get(format, index, field, setter); - } + // PARSING - var i; - var out = []; - for (i = 0; i < count; i++) { - out[i] = lists__get(format, i, field, setter); - } - return out; - } + addRegexToken('x', matchSigned); + addRegexToken('X', matchTimestamp); + addParseToken('X', function (input, array, config) { + config._d = new Date(parseFloat(input, 10) * 1000); + }); + addParseToken('x', function (input, array, config) { + config._d = new Date(toInt(input)); + }); - function lists__listMonths (format, index) { - return list(format, index, 'months', 12, 'month'); - } + // Side effect imports - function lists__listMonthsShort (format, index) { - return list(format, index, 'monthsShort', 12, 'month'); - } - function lists__listWeekdays (format, index) { - return list(format, index, 'weekdays', 7, 'day'); - } + utils_hooks__hooks.version = '2.10.2'; - function lists__listWeekdaysShort (format, index) { - return list(format, index, 'weekdaysShort', 7, 'day'); - } + setHookCallback(local__createLocal); - function lists__listWeekdaysMin (format, index) { - return list(format, index, 'weekdaysMin', 7, 'day'); - } + utils_hooks__hooks.fn = momentPrototype; + utils_hooks__hooks.min = min; + utils_hooks__hooks.max = max; + utils_hooks__hooks.utc = create_utc__createUTC; + utils_hooks__hooks.unix = moment__createUnix; + utils_hooks__hooks.months = lists__listMonths; + utils_hooks__hooks.isDate = isDate; + utils_hooks__hooks.locale = locale_locales__getSetGlobalLocale; + utils_hooks__hooks.invalid = valid__createInvalid; + utils_hooks__hooks.duration = create__createDuration; + utils_hooks__hooks.isMoment = isMoment; + utils_hooks__hooks.weekdays = lists__listWeekdays; + utils_hooks__hooks.parseZone = moment__createInZone; + utils_hooks__hooks.localeData = locale_locales__getLocale; + utils_hooks__hooks.isDuration = isDuration; + utils_hooks__hooks.monthsShort = lists__listMonthsShort; + utils_hooks__hooks.weekdaysMin = lists__listWeekdaysMin; + utils_hooks__hooks.defineLocale = defineLocale; + utils_hooks__hooks.weekdaysShort = lists__listWeekdaysShort; + utils_hooks__hooks.normalizeUnits = normalizeUnits; + utils_hooks__hooks.relativeTimeThreshold = duration_humanize__getSetRelativeTimeThreshold; - locale_locales__getSetGlobalLocale('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; - } - }); + var _moment = utils_hooks__hooks; - // Side effect imports - utils_hooks__hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', locale_locales__getSetGlobalLocale); - utils_hooks__hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', locale_locales__getLocale); + return _moment; - var mathAbs = Math.abs; + })); + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(83)(module))) - function duration_abs__abs () { - var data = this._data; +/***/ }, +/* 65 */ +/***/ function(module, exports, __webpack_require__) { - this._milliseconds = mathAbs(this._milliseconds); - this._days = mathAbs(this._days); - this._months = mathAbs(this._months); + var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;'use strict'; - data.milliseconds = mathAbs(data.milliseconds); - data.seconds = mathAbs(data.seconds); - data.minutes = mathAbs(data.minutes); - data.hours = mathAbs(data.hours); - data.months = mathAbs(data.months); - data.years = mathAbs(data.years); + (function (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) + window.propagating = factory(); + } + }(function () { + var _firstTarget = null; // singleton, will contain the target element where the touch event started + var _processing = false; // singleton, true when a touch event is being handled - return this; + /** + * Extend an Hammer.js instance with event propagation. + * + * Features: + * - Events emitted by hammer will propagate in order from child to parent + * elements. + * - Events are extended with a function `event.stopPropagation()` to stop + * propagation to parent elements. + * - An option `preventDefault` to stop all default browser behavior. + * + * Usage: + * var hammer = propagatingHammer(new Hammer(element)); + * var hammer = propagatingHammer(new Hammer(element), {preventDefault: true}); + * + * @param {Hammer.Manager} hammer An hammer instance. + * @param {Object} [options] Available options: + * - `preventDefault: boolean` (false by default) + * @return {Hammer.Manager} Returns the same hammer instance with extended + * functionality + */ + return function propagating(hammer, options) { + if (options && options.preventDefault === false) { + throw new Error('Only supports preventDefault == true'); } + var _options = options || { + preventDefault: false + }; - function duration_add_subtract__addSubtract (duration, input, value, direction) { - var other = create__createDuration(input, value); + if (hammer.Manager) { + // This looks like the Hammer constructor. + // Overload the constructors with our own. + var Hammer = hammer; - duration._milliseconds += direction * other._milliseconds; - duration._days += direction * other._days; - duration._months += direction * other._months; + var PropagatingHammer = function(element, options) { + return propagating(new Hammer(element, options), _options); + }; + Hammer.extend(PropagatingHammer, Hammer); + PropagatingHammer.Manager = function (element, options) { + return propagating(new Hammer.Manager(element, options), _options); + }; - return duration._bubble(); + return PropagatingHammer; } - // supports only 2.0-style add(1, 's') or add(duration) - function duration_add_subtract__add (input, value) { - return duration_add_subtract__addSubtract(this, input, value, 1); - } + // attach to DOM element + var element = hammer.element; + element.hammer = hammer; - // supports only 2.0-style subtract(1, 's') or subtract(duration) - function duration_add_subtract__subtract (input, value) { - return duration_add_subtract__addSubtract(this, input, value, -1); - } + // move the original functions that we will wrap + hammer._on = hammer.on; + hammer._off = hammer.off; + hammer._emit = hammer.emit; + hammer._destroy = hammer.destroy; - function bubble () { - var milliseconds = this._milliseconds; - var days = this._days; - var months = this._months; - var data = this._data; - var seconds, minutes, hours, years = 0; + /** @type {Object.>} */ + hammer._handlers = {}; - // The following code bubbles up values, see the tests for - // examples of what that means. - data.milliseconds = milliseconds % 1000; + // register an event to catch the start of a gesture and store the + // target in a singleton + hammer._on('hammer.input', function (event) { + if (_options.preventDefault) { + event.preventDefault(); + } + if (event.isFirst) { + _firstTarget = event.target; + _processing = true; + } + if (event.isFinal) { + _processing = false; + } + }); - seconds = absFloor(milliseconds / 1000); - data.seconds = seconds % 60; + /** + * Register a handler for one or multiple events + * @param {String} events A space separated string with events + * @param {function} handler A callback function, called as handler(event) + * @returns {Hammer.Manager} Returns the hammer instance + */ + hammer.on = function (events, handler) { + // register the handler + split(events).forEach(function (event) { + var _handlers = hammer._handlers[event]; + if (!_handlers) { + hammer._handlers[event] = _handlers = []; - minutes = absFloor(seconds / 60); - data.minutes = minutes % 60; + // register the static, propagated handler + hammer._on(event, propagatedHandler); + } + _handlers.push(handler); + }); - hours = absFloor(minutes / 60); - data.hours = hours % 24; + return hammer; + }; - days += absFloor(hours / 24); + /** + * Unregister a handler for one or multiple events + * @param {String} events A space separated string with events + * @param {function} [handler] Optional. The registered handler. If not + * provided, all handlers for given events + * are removed. + * @returns {Hammer.Manager} Returns the hammer instance + */ + hammer.off = function (events, handler) { + // unregister the handler + split(events).forEach(function (event) { + var _handlers = hammer._handlers[event]; + if (_handlers) { + _handlers = handler ? _handlers.filter(function (h) { + return h !== handler; + }) : []; - // Accurately convert days to years, assume start from year 0. - years = absFloor(daysToYears(days)); - days -= absFloor(yearsToDays(years)); + if (_handlers.length > 0) { + hammer._handlers[event] = _handlers; + } + else { + // remove static, propagated handler + hammer._off(event, propagatedHandler); + delete hammer._handlers[event]; + } + } + }); - // 30 days to a month - // TODO (iskren): Use anchor date (like 1st Jan) to compute this. - months += absFloor(days / 30); - days %= 30; + return hammer; + }; - // 12 months -> 1 year - years += absFloor(months / 12); - months %= 12; + /** + * Emit to the event listeners + * @param {string} eventType + * @param {Event} event + */ + hammer.emit = function(eventType, event) { + if (!_processing) { + _firstTarget = event.target; + } + hammer._emit(eventType, event); + }; - data.days = days; - data.months = months; - data.years = years; + hammer.destroy = function () { + // Detach from DOM element + var element = hammer.element; + delete element.hammer; - return this; - } + // clear all handlers + hammer._handlers = {}; - function daysToYears (days) { - // 400 years have 146097 days (taking into account leap year rules) - return days * 400 / 146097; - } + // call original hammer destroy + hammer._destroy(); + }; - function yearsToDays (years) { - // years * 365 + absFloor(years / 4) - - // absFloor(years / 100) + absFloor(years / 400); - return years * 146097 / 400; + // split a string with space separated words + function split(events) { + return events.match(/[^ ]+/g); } - function as (units) { - var days; - var months; - var milliseconds = this._milliseconds; - - units = normalizeUnits(units); - - if (units === 'month' || units === 'year') { - days = this._days + 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 + milliseconds / 6048e5; - case 'day' : return days + milliseconds / 864e5; - case 'hour' : return days * 24 + milliseconds / 36e5; - case 'minute' : return days * 24 * 60 + milliseconds / 6e4; - case 'second' : return days * 24 * 60 * 60 + milliseconds / 1000; - // Math.floor prevents floating point math errors here - case 'millisecond': return Math.floor(days * 24 * 60 * 60 * 1000) + milliseconds; - default: throw new Error('Unknown unit ' + units); - } + /** + * A static event handler, applying event propagation. + * @param {Object} event + */ + function propagatedHandler(event) { + // let only a single hammer instance handle this event + if (event.type !== 'hammer.input') { + if (event.srcEvent._handled && event.srcEvent._handled[event.type]) { + return; } - } + else { + // it is possible that the same srcEvent is used with multiple hammer events + event.srcEvent._handled = {}; + event.srcEvent._handled[event.type] = true; + } + } - // TODO: Use this.as('ms')? - function duration_as__valueOf () { - return ( - this._milliseconds + - this._days * 864e5 + - (this._months % 12) * 2592e6 + - toInt(this._months / 12) * 31536e6 - ); - } + // attach a stopPropagation function to the event + var stopped = false; + event.stopPropagation = function () { + stopped = true; + }; - function makeAs (alias) { - return function () { - return this.as(alias); - }; - } + // attach firstTarget property to the event + event.firstTarget = _firstTarget; - var asMilliseconds = makeAs('ms'); - var asSeconds = makeAs('s'); - var asMinutes = makeAs('m'); - var asHours = makeAs('h'); - var asDays = makeAs('d'); - var asWeeks = makeAs('w'); - var asMonths = makeAs('M'); - var asYears = makeAs('y'); + // propagate over all elements (until stopped) + var elem = _firstTarget; + while (elem && !stopped) { + var _handlers = elem.hammer && elem.hammer._handlers[event.type]; + if (_handlers) { + for (var i = 0; i < _handlers.length && !stopped; i++) { + _handlers[i](event); + } + } - function duration_get__get (units) { - units = normalizeUnits(units); - return this[units + 's'](); + elem = elem.parentNode; + } } - function makeGetter(name) { - return function () { - return this._data[name]; - }; - } + return hammer; + }; + })); - var duration_get__milliseconds = makeGetter('milliseconds'); - var seconds = makeGetter('seconds'); - var minutes = makeGetter('minutes'); - var hours = makeGetter('hours'); - var days = makeGetter('days'); - var months = makeGetter('months'); - var years = makeGetter('years'); - function weeks () { - return absFloor(this.days() / 7); - } +/***/ }, +/* 66 */ +/***/ function(module, exports, __webpack_require__) { - var round = Math.round; - var thresholds = { - 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 - }; + var __WEBPACK_AMD_DEFINE_RESULT__;/*! Hammer.JS - v2.0.4 - 2014-09-28 + * http://hammerjs.github.io/ + * + * Copyright (c) 2014 Jorik Tangelder; + * Licensed under the MIT license */ + (function(window, document, exportName, undefined) { + 'use strict'; - // 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); - } + var VENDOR_PREFIXES = ['', 'webkit', 'moz', 'MS', 'ms', 'o']; + var TEST_ELEMENT = document.createElement('div'); - function duration_humanize__relativeTime (posNegDuration, withoutSuffix, locale) { - var duration = create__createDuration(posNegDuration).abs(); - var seconds = round(duration.as('s')); - var minutes = round(duration.as('m')); - var hours = round(duration.as('h')); - var days = round(duration.as('d')); - var months = round(duration.as('M')); - var years = round(duration.as('y')); + var TYPE_FUNCTION = 'function'; - var a = seconds < thresholds.s && ['s', seconds] || - minutes === 1 && ['m'] || - minutes < thresholds.m && ['mm', minutes] || - hours === 1 && ['h'] || - hours < thresholds.h && ['hh', hours] || - days === 1 && ['d'] || - days < thresholds.d && ['dd', days] || - months === 1 && ['M'] || - months < thresholds.M && ['MM', months] || - years === 1 && ['y'] || ['yy', years]; + var round = Math.round; + var abs = Math.abs; + var now = Date.now; - a[2] = withoutSuffix; - a[3] = +posNegDuration > 0; - a[4] = locale; - return substituteTimeAgo.apply(null, a); - } + /** + * set a timeout with a given scope + * @param {Function} fn + * @param {Number} timeout + * @param {Object} context + * @returns {number} + */ + function setTimeoutContext(fn, timeout, context) { + return setTimeout(bindFn(fn, context), timeout); + } - // This function allows you to set a threshold for relative time strings - function duration_humanize__getSetRelativeTimeThreshold (threshold, limit) { - if (thresholds[threshold] === undefined) { - return false; - } - if (limit === undefined) { - return thresholds[threshold]; - } - thresholds[threshold] = limit; + /** + * if the argument is an array, we want to execute the fn on each entry + * if it aint an array we don't want to do a thing. + * this is used by all the methods that accept a single and array argument. + * @param {*|Array} arg + * @param {String} fn + * @param {Object} [context] + * @returns {Boolean} + */ + function invokeArrayArg(arg, fn, context) { + if (Array.isArray(arg)) { + each(arg, context[fn], context); return true; } + return false; + } - function humanize (withSuffix) { - var locale = this.localeData(); - var output = duration_humanize__relativeTime(this, !withSuffix, locale); - - if (withSuffix) { - output = locale.pastFuture(+this, output); - } + /** + * walk objects and arrays + * @param {Object} obj + * @param {Function} iterator + * @param {Object} context + */ + function each(obj, iterator, context) { + var i; - return locale.postformat(output); + if (!obj) { + return; } - var iso_string__abs = Math.abs; - - function iso_string__toISOString() { - // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js - var Y = iso_string__abs(this.years()); - var M = iso_string__abs(this.months()); - var D = iso_string__abs(this.days()); - var h = iso_string__abs(this.hours()); - var m = iso_string__abs(this.minutes()); - var s = iso_string__abs(this.seconds() + this.milliseconds() / 1000); - var total = this.asSeconds(); - - if (!total) { - // this is the same as C#'s (Noda) and python (isodate)... - // but not other JS (goog.date) - return 'P0D'; + if (obj.forEach) { + obj.forEach(iterator, context); + } else if (obj.length !== undefined) { + i = 0; + while (i < obj.length) { + iterator.call(context, obj[i], i, obj); + i++; } + } else { + for (i in obj) { + obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj); + } + } + } - return (total < 0 ? '-' : '') + - 'P' + - (Y ? Y + 'Y' : '') + - (M ? M + 'M' : '') + - (D ? D + 'D' : '') + - ((h || m || s) ? 'T' : '') + - (h ? h + 'H' : '') + - (m ? m + 'M' : '') + - (s ? s + 'S' : ''); + /** + * extend object. + * means that properties in dest will be overwritten by the ones in src. + * @param {Object} dest + * @param {Object} src + * @param {Boolean} [merge] + * @returns {Object} dest + */ + function extend(dest, src, merge) { + var keys = Object.keys(src); + var i = 0; + while (i < keys.length) { + if (!merge || (merge && dest[keys[i]] === undefined)) { + dest[keys[i]] = src[keys[i]]; + } + i++; } + return dest; + } - var duration_prototype__proto = Duration.prototype; + /** + * merge the values from src in the dest. + * means that properties that exist in dest will not be overwritten by src + * @param {Object} dest + * @param {Object} src + * @returns {Object} dest + */ + function merge(dest, src) { + return extend(dest, src, true); + } - duration_prototype__proto.abs = duration_abs__abs; - duration_prototype__proto.add = duration_add_subtract__add; - duration_prototype__proto.subtract = duration_add_subtract__subtract; - duration_prototype__proto.as = as; - duration_prototype__proto.asMilliseconds = asMilliseconds; - duration_prototype__proto.asSeconds = asSeconds; - duration_prototype__proto.asMinutes = asMinutes; - duration_prototype__proto.asHours = asHours; - duration_prototype__proto.asDays = asDays; - duration_prototype__proto.asWeeks = asWeeks; - duration_prototype__proto.asMonths = asMonths; - duration_prototype__proto.asYears = asYears; - duration_prototype__proto.valueOf = duration_as__valueOf; - duration_prototype__proto._bubble = bubble; - duration_prototype__proto.get = duration_get__get; - duration_prototype__proto.milliseconds = duration_get__milliseconds; - duration_prototype__proto.seconds = seconds; - duration_prototype__proto.minutes = minutes; - duration_prototype__proto.hours = hours; - duration_prototype__proto.days = days; - duration_prototype__proto.weeks = weeks; - duration_prototype__proto.months = months; - duration_prototype__proto.years = years; - duration_prototype__proto.humanize = humanize; - duration_prototype__proto.toISOString = iso_string__toISOString; - duration_prototype__proto.toString = iso_string__toISOString; - duration_prototype__proto.toJSON = iso_string__toISOString; - duration_prototype__proto.locale = locale; - duration_prototype__proto.localeData = localeData; + /** + * simple class inheritance + * @param {Function} child + * @param {Function} base + * @param {Object} [properties] + */ + function inherit(child, base, properties) { + var baseP = base.prototype, + childP; - // Deprecations - duration_prototype__proto.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', iso_string__toISOString); - duration_prototype__proto.lang = lang; + childP = child.prototype = Object.create(baseP); + childP.constructor = child; + childP._super = baseP; - // Side effect imports + if (properties) { + extend(childP, properties); + } + } + + /** + * simple function bind + * @param {Function} fn + * @param {Object} context + * @returns {Function} + */ + function bindFn(fn, context) { + return function boundFn() { + return fn.apply(context, arguments); + }; + } - addFormatToken('X', 0, 0, 'unix'); - addFormatToken('x', 0, 0, 'valueOf'); + /** + * let a boolean value also be a function that must return a boolean + * this first item in args will be used as the context + * @param {Boolean|Function} val + * @param {Array} [args] + * @returns {Boolean} + */ + function boolOrFn(val, args) { + if (typeof val == TYPE_FUNCTION) { + return val.apply(args ? args[0] || undefined : undefined, args); + } + return val; + } - // PARSING + /** + * use the val2 when val1 is undefined + * @param {*} val1 + * @param {*} val2 + * @returns {*} + */ + function ifUndefined(val1, val2) { + return (val1 === undefined) ? val2 : val1; + } - addRegexToken('x', matchSigned); - addRegexToken('X', matchTimestamp); - addParseToken('X', function (input, array, config) { - config._d = new Date(parseFloat(input, 10) * 1000); - }); - addParseToken('x', function (input, array, config) { - config._d = new Date(toInt(input)); + /** + * addEventListener with multiple events at once + * @param {EventTarget} target + * @param {String} types + * @param {Function} handler + */ + function addEventListeners(target, types, handler) { + each(splitStr(types), function(type) { + target.addEventListener(type, handler, false); }); + } - // Side effect imports - + /** + * removeEventListener with multiple events at once + * @param {EventTarget} target + * @param {String} types + * @param {Function} handler + */ + function removeEventListeners(target, types, handler) { + each(splitStr(types), function(type) { + target.removeEventListener(type, handler, false); + }); + } - utils_hooks__hooks.version = '2.10.2'; + /** + * find if a node is in the given parent + * @method hasParent + * @param {HTMLElement} node + * @param {HTMLElement} parent + * @return {Boolean} found + */ + function hasParent(node, parent) { + while (node) { + if (node == parent) { + return true; + } + node = node.parentNode; + } + return false; + } - setHookCallback(local__createLocal); + /** + * small indexOf wrapper + * @param {String} str + * @param {String} find + * @returns {Boolean} found + */ + function inStr(str, find) { + return str.indexOf(find) > -1; + } - utils_hooks__hooks.fn = momentPrototype; - utils_hooks__hooks.min = min; - utils_hooks__hooks.max = max; - utils_hooks__hooks.utc = create_utc__createUTC; - utils_hooks__hooks.unix = moment__createUnix; - utils_hooks__hooks.months = lists__listMonths; - utils_hooks__hooks.isDate = isDate; - utils_hooks__hooks.locale = locale_locales__getSetGlobalLocale; - utils_hooks__hooks.invalid = valid__createInvalid; - utils_hooks__hooks.duration = create__createDuration; - utils_hooks__hooks.isMoment = isMoment; - utils_hooks__hooks.weekdays = lists__listWeekdays; - utils_hooks__hooks.parseZone = moment__createInZone; - utils_hooks__hooks.localeData = locale_locales__getLocale; - utils_hooks__hooks.isDuration = isDuration; - utils_hooks__hooks.monthsShort = lists__listMonthsShort; - utils_hooks__hooks.weekdaysMin = lists__listWeekdaysMin; - utils_hooks__hooks.defineLocale = defineLocale; - utils_hooks__hooks.weekdaysShort = lists__listWeekdaysShort; - utils_hooks__hooks.normalizeUnits = normalizeUnits; - utils_hooks__hooks.relativeTimeThreshold = duration_humanize__getSetRelativeTimeThreshold; + /** + * split string on whitespace + * @param {String} str + * @returns {Array} words + */ + function splitStr(str) { + return str.trim().split(/\s+/g); + } - var _moment = utils_hooks__hooks; + /** + * find if a array contains the object using indexOf or a simple polyFill + * @param {Array} src + * @param {String} find + * @param {String} [findByKey] + * @return {Boolean|Number} false when not found, or the index + */ + function inArray(src, find, findByKey) { + if (src.indexOf && !findByKey) { + return src.indexOf(find); + } else { + var i = 0; + while (i < src.length) { + if ((findByKey && src[i][findByKey] == find) || (!findByKey && src[i] === find)) { + return i; + } + i++; + } + return -1; + } + } - return _moment; + /** + * convert array-like objects to real arrays + * @param {Object} obj + * @returns {Array} + */ + function toArray(obj) { + return Array.prototype.slice.call(obj, 0); + } - })); - /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(68)(module))) + /** + * unique array with objects based on a key (like 'id') or just by the array's value + * @param {Array} src [{id:1},{id:2},{id:1}] + * @param {String} [key] + * @param {Boolean} [sort=False] + * @returns {Array} [{id:1},{id:2}] + */ + function uniqueArray(src, key, sort) { + var results = []; + var values = []; + var i = 0; -/***/ }, -/* 64 */ -/***/ function(module, exports, __webpack_require__) { + while (i < src.length) { + var val = key ? src[i][key] : src[i]; + if (inArray(values, val) < 0) { + results.push(src[i]); + } + values[i] = val; + i++; + } - "use strict"; + if (sort) { + if (!key) { + results = results.sort(); + } else { + results = results.sort(function sortUniqueArray(a, b) { + return a[key] > b[key]; + }); + } + } - var Hammer = __webpack_require__(41); + return results; + } /** - * Register a touch event, taking place before a gesture - * @param {Hammer} hammer A hammer instance - * @param {function} callback Callback, called as callback(event) + * get the prefixed property + * @param {Object} obj + * @param {String} property + * @returns {String|Undefined} prefixed */ - exports.onTouch = function (hammer, callback) { - callback.inputHandler = function (event) { - if (event.isFirst) { - callback(event); - } - }; + function prefixed(obj, property) { + var prefix, prop; + var camelProp = property[0].toUpperCase() + property.slice(1); - hammer.on("hammer.input", callback.inputHandler); - }; + var i = 0; + while (i < VENDOR_PREFIXES.length) { + prefix = VENDOR_PREFIXES[i]; + prop = (prefix) ? prefix + camelProp : property; - /** - * Register a release event, taking place after a gesture - * @param {Hammer} hammer A hammer instance - * @param {function} callback Callback, called as callback(event) - */ - exports.onRelease = function (hammer, callback) { - callback.inputHandler = function (event) { - if (event.isFinal) { - callback(event); + if (prop in obj) { + return prop; + } + i++; } - }; + return undefined; + } - return hammer.on("hammer.input", callback.inputHandler); - }; + /** + * get a unique id + * @returns {number} uniqueId + */ + var _uniqueId = 1; + function uniqueId() { + return _uniqueId++; + } /** - * Unregister a touch event, taking place before a gesture - * @param {Hammer} hammer A hammer instance - * @param {function} callback Callback, called as callback(event) + * get the window object of an element + * @param {HTMLElement} element + * @returns {DocumentView|Window} */ - exports.offTouch = function (hammer, callback) { - hammer.off("hammer.input", callback.inputHandler); - }; + function getWindowForElement(element) { + var doc = element.ownerDocument; + return (doc.defaultView || doc.parentWindow); + } + + var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i; + + var SUPPORT_TOUCH = ('ontouchstart' in window); + var SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined; + var SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent); + + var INPUT_TYPE_TOUCH = 'touch'; + var INPUT_TYPE_PEN = 'pen'; + var INPUT_TYPE_MOUSE = 'mouse'; + var INPUT_TYPE_KINECT = 'kinect'; + + var COMPUTE_INTERVAL = 25; + + var INPUT_START = 1; + var INPUT_MOVE = 2; + var INPUT_END = 4; + var INPUT_CANCEL = 8; + + var DIRECTION_NONE = 1; + var DIRECTION_LEFT = 2; + var DIRECTION_RIGHT = 4; + var DIRECTION_UP = 8; + var DIRECTION_DOWN = 16; - /** - * Unregister a release event, taking place before a gesture - * @param {Hammer} hammer A hammer instance - * @param {function} callback Callback, called as callback(event) - */ - exports.offRelease = exports.offTouch; + var DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT; + var DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN; + var DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL; -/***/ }, -/* 65 */ -/***/ function(module, exports, __webpack_require__) { + var PROPS_XY = ['x', 'y']; + var PROPS_CLIENT_XY = ['clientX', 'clientY']; - var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;"use strict"; /** - * Created by Alex on 11/6/2014. + * create new input type manager + * @param {Manager} manager + * @param {Function} callback + * @returns {Input} + * @constructor */ + function Input(manager, callback) { + var self = this; + this.manager = manager; + this.callback = callback; + this.element = manager.element; + this.target = manager.options.inputTarget; - // 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; + // smaller wrapper around the handler, for the scope and the enabled state of the manager, + // so when disabled the input events are completely bypassed. + this.domHandler = function(ev) { + if (boolOrFn(manager.options.enable, [manager])) { + self.handler(ev); + } + }; - // 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.init(); - // 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}; + } + Input.prototype = { + /** + * should handle the inputEvent data and trigger the callback + * @virtual + */ + handler: function() { }, + /** + * bind the events + */ + init: function() { + this.evEl && addEventListeners(this.element, this.evEl, this.domHandler); + this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler); + this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); + }, - var down = function(event) {handleEvent(event,'keydown');}; - var up = function(event) {handleEvent(event,'keyup');}; + /** + * unbind the events + */ + destroy: function() { + this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler); + this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler); + this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); + } + }; - // 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); - } - } + /** + * create new input type manager + * called by the Manager constructor + * @param {Hammer} manager + * @returns {Input} + */ + function createInputInstance(manager) { + var Type; + var inputClass = manager.options.inputClass; - if (preventDefault == true) { - event.preventDefault(); - } - } - }; + if (inputClass) { + Type = inputClass; + } else if (SUPPORT_POINTER_EVENTS) { + Type = PointerEventInput; + } else if (SUPPORT_ONLY_TOUCH) { + Type = TouchInput; + } else if (!SUPPORT_TOUCH) { + Type = MouseInput; + } else { + Type = TouchMouseInput; + } + return new (Type)(manager, inputHandler); + } - // 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}); - }; + /** + * handle input events + * @param {Manager} manager + * @param {String} eventType + * @param {Object} input + */ + function inputHandler(manager, eventType, input) { + var pointersLen = input.pointers.length; + var changedPointersLen = input.changedPointers.length; + var isFirst = (eventType & INPUT_START && (pointersLen - changedPointersLen === 0)); + var isFinal = (eventType & (INPUT_END | INPUT_CANCEL) && (pointersLen - changedPointersLen === 0)); + input.isFirst = !!isFirst; + input.isFinal = !!isFinal; - // 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); - } - } - }; + if (isFirst) { + manager.session = {}; + } - // 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"; - }; + // source event is the normalized value of the domEvents + // like 'touchstart, mouseup, pointerdown' + input.eventType = eventType; - // 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] = []; - } - }; + // compute scale, rotation etc + computeInputData(manager, input); - // reset all bound variables. - _exportFunctions.reset = function() { - _bound = {keydown:{}, keyup:{}}; - }; + // emit secret event + manager.emit('hammer.input', input); - // unbind all listeners and reset all variables. - _exportFunctions.destroy = function() { - _bound = {keydown:{}, keyup:{}}; - container.removeEventListener('keydown', down, true); - container.removeEventListener('keyup', up, true); - }; + manager.recognize(input); + manager.session.prevInput = input; + } - // create listeners. - container.addEventListener('keydown',down,true); - container.addEventListener('keyup',up,true); + /** + * extend the data with some usable properties like scale, rotate, velocity etc + * @param {Object} manager + * @param {Object} input + */ + function computeInputData(manager, input) { + var session = manager.session; + var pointers = input.pointers; + var pointersLength = pointers.length; - // return the public functions. - return _exportFunctions; - } + // store the first input to calculate the distance and direction + if (!session.firstInput) { + session.firstInput = simpleCloneInputData(input); + } - return keycharm; - })); + // to compute scale and rotation we need to store the multiple touches + if (pointersLength > 1 && !session.firstMultiple) { + session.firstMultiple = simpleCloneInputData(input); + } else if (pointersLength === 1) { + session.firstMultiple = false; + } + var firstInput = session.firstInput; + var firstMultiple = session.firstMultiple; + var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center; + var center = input.center = getCenter(pointers); + input.timeStamp = now(); + input.deltaTime = input.timeStamp - firstInput.timeStamp; + input.angle = getAngle(offsetCenter, center); + input.distance = getDistance(offsetCenter, center); -/***/ }, -/* 66 */ -/***/ function(module, exports, __webpack_require__) { + computeDeltaXY(session, input); + input.offsetDirection = getDirection(input.deltaX, input.deltaY); - "use strict"; + input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1; + input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0; - // 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.", - editClusterError: "Clusters cannot be edited." - }; - exports.en_EN = exports.en; - exports.en_US = exports.en; + computeIntervalInputData(session, input); - // 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.", - editClusterError: "Clusters kunnen niet worden aangepast." - }; - exports.nl_NL = exports.nl; - exports.nl_BE = exports.nl; + // find the correct target + var target = manager.element; + if (hasParent(input.srcEvent.target, target)) { + target = input.srcEvent.target; + } + input.target = target; + } -/***/ }, -/* 67 */ -/***/ function(module, exports, __webpack_require__) { + function computeDeltaXY(session, input) { + var center = input.center; + var offset = session.offsetDelta || {}; + var prevDelta = session.prevDelta || {}; + var prevInput = session.prevInput || {}; - function webpackContext(req) { - throw new Error("Cannot find module '" + req + "'."); + if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) { + prevDelta = session.prevDelta = { + x: prevInput.deltaX || 0, + y: prevInput.deltaY || 0 + }; + + offset = session.offsetDelta = { + x: center.x, + y: center.y + }; + } + + input.deltaX = prevDelta.x + (center.x - offset.x); + input.deltaY = prevDelta.y + (center.y - offset.y); } - webpackContext.keys = function() { return []; }; - webpackContext.resolve = webpackContext; - module.exports = webpackContext; - webpackContext.id = 67; + /** + * velocity is calculated every x ms + * @param {Object} session + * @param {Object} input + */ + function computeIntervalInputData(session, input) { + var last = session.lastInterval || input, + deltaTime = input.timeStamp - last.timeStamp, + velocity, velocityX, velocityY, direction; -/***/ }, -/* 68 */ -/***/ function(module, exports, __webpack_require__) { + if (input.eventType != INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) { + var deltaX = last.deltaX - input.deltaX; + var deltaY = last.deltaY - input.deltaY; - module.exports = function(module) { - if(!module.webpackPolyfill) { - module.deprecate = function() {}; - module.paths = []; - // module.parent = undefined by default - module.children = []; - module.webpackPolyfill = 1; - } - return module; + var v = getVelocity(deltaTime, deltaX, deltaY); + velocityX = v.x; + velocityY = v.y; + velocity = (abs(v.x) > abs(v.y)) ? v.x : v.y; + direction = getDirection(deltaX, deltaY); + + session.lastInterval = input; + } else { + // use latest velocity info if it doesn't overtake a minimum period + velocity = last.velocity; + velocityX = last.velocityX; + velocityY = last.velocityY; + direction = last.direction; + } + + input.velocity = velocity; + input.velocityX = velocityX; + input.velocityY = velocityY; + input.direction = direction; } + /** + * create a simple clone from the input used for storage of firstInput and firstMultiple + * @param {Object} input + * @returns {Object} clonedInputData + */ + function simpleCloneInputData(input) { + // make a simple copy of the pointers because we will get a reference if we don't + // we only need clientXY for the calculations + var pointers = []; + var i = 0; + while (i < input.pointers.length) { + pointers[i] = { + clientX: round(input.pointers[i].clientX), + clientY: round(input.pointers[i].clientY) + }; + i++; + } -/***/ }, -/* 69 */ -/***/ function(module, exports, __webpack_require__) { + return { + timeStamp: now(), + pointers: pointers, + center: getCenter(pointers), + deltaX: input.deltaX, + deltaY: input.deltaY + }; + } - var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;'use strict'; + /** + * get the center of all the pointers + * @param {Array} pointers + * @return {Object} center contains `x` and `y` properties + */ + function getCenter(pointers) { + var pointersLength = pointers.length; - (function (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) - window.propagating = factory(); - } - }(function () { - // will contain the target element where the gesture started - var _firstTarget = null; // singleton + // no need to loop when only one touch + if (pointersLength === 1) { + return { + x: round(pointers[0].clientX), + y: round(pointers[0].clientY) + }; + } - /** - * Extend an Hammer.js instance with event propagation. - * - * Features: - * - Events emitted by hammer will propagate in order from child to parent - * elements. - * - Events are extended with a function `event.stopPropagation()` to stop - * propagation to parent elements. - * - * Usage: - * var hammer = propagatingHammer(new Hammer(element)); - * - * @param {Hammer.Manager} hammer An hammer instance. - * @return {Hammer.Manager} Returns the same hammer instance with extended - * functionality - */ - return function propagating(hammer) { - if (hammer.Manager) { - // This looks like the Hammer constructor. - // Overload the constructors with our own. - var Hammer = hammer; + var x = 0, y = 0, i = 0; + while (i < pointersLength) { + x += pointers[i].clientX; + y += pointers[i].clientY; + i++; + } - var PropagatingHammer = function(element, options) { - return propagating(new Hammer(element, options)); - }; - Hammer.extend(PropagatingHammer, Hammer); - PropagatingHammer.Manager = function (element, options) { - return propagating(new Hammer.Manager(element, options)); - }; + return { + x: round(x / pointersLength), + y: round(y / pointersLength) + }; + } + + /** + * calculate the velocity between two points. unit is in px per ms. + * @param {Number} deltaTime + * @param {Number} x + * @param {Number} y + * @return {Object} velocity `x` and `y` + */ + function getVelocity(deltaTime, x, y) { + return { + x: x / deltaTime || 0, + y: y / deltaTime || 0 + }; + } + + /** + * get the direction between two points + * @param {Number} x + * @param {Number} y + * @return {Number} direction + */ + function getDirection(x, y) { + if (x === y) { + return DIRECTION_NONE; + } - return PropagatingHammer; + if (abs(x) >= abs(y)) { + return x > 0 ? DIRECTION_LEFT : DIRECTION_RIGHT; } + return y > 0 ? DIRECTION_UP : DIRECTION_DOWN; + } - // attach to DOM element - var element = hammer.element; - element.hammer = hammer; + /** + * calculate the absolute distance between two points + * @param {Object} p1 {x, y} + * @param {Object} p2 {x, y} + * @param {Array} [props] containing x and y keys + * @return {Number} distance + */ + function getDistance(p1, p2, props) { + if (!props) { + props = PROPS_XY; + } + var x = p2[props[0]] - p1[props[0]], + y = p2[props[1]] - p1[props[1]]; - // move the original functions that we will wrap - hammer._on = hammer.on; - hammer._off = hammer.off; - hammer._emit = hammer.emit; - hammer._destroy = hammer.destroy; + return Math.sqrt((x * x) + (y * y)); + } - /** @type {Object.>} */ - hammer._handlers = {}; + /** + * calculate the angle between two coordinates + * @param {Object} p1 + * @param {Object} p2 + * @param {Array} [props] containing x and y keys + * @return {Number} angle + */ + function getAngle(p1, p2, props) { + if (!props) { + props = PROPS_XY; + } + var x = p2[props[0]] - p1[props[0]], + y = p2[props[1]] - p1[props[1]]; + return Math.atan2(y, x) * 180 / Math.PI; + } - // register an event to catch the start of a gesture and store the - // target in a singleton - hammer._on('hammer.input', function (event) { - if (event.isFirst) { - _firstTarget = event.target; - } - }); + /** + * calculate the rotation degrees between two pointersets + * @param {Array} start array of pointers + * @param {Array} end array of pointers + * @return {Number} rotation + */ + function getRotation(start, end) { + return getAngle(end[1], end[0], PROPS_CLIENT_XY) - getAngle(start[1], start[0], PROPS_CLIENT_XY); + } - /** - * Register a handler for one or multiple events - * @param {String} events A space separated string with events - * @param {function} handler A callback function, called as handler(event) - * @returns {Hammer.Manager} Returns the hammer instance - */ - hammer.on = function (events, handler) { - // register the handler - split(events).forEach(function (event) { - var _handlers = hammer._handlers[event]; - if (!_handlers) { - hammer._handlers[event] = _handlers = []; + /** + * calculate the scale factor between two pointersets + * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out + * @param {Array} start array of pointers + * @param {Array} end array of pointers + * @return {Number} scale + */ + function getScale(start, end) { + return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY); + } - // register the static, propagated handler - hammer._on(event, propagatedHandler); - } - _handlers.push(handler); - }); + var MOUSE_INPUT_MAP = { + mousedown: INPUT_START, + mousemove: INPUT_MOVE, + mouseup: INPUT_END + }; - return hammer; - }; + var MOUSE_ELEMENT_EVENTS = 'mousedown'; + var MOUSE_WINDOW_EVENTS = 'mousemove mouseup'; - /** - * Unregister a handler for one or multiple events - * @param {String} events A space separated string with events - * @param {function} [handler] Optional. The registered handler. If not - * provided, all handlers for given events - * are removed. - * @returns {Hammer.Manager} Returns the hammer instance - */ - hammer.off = function (events, handler) { - // unregister the handler - split(events).forEach(function (event) { - var _handlers = hammer._handlers[event]; - if (_handlers) { - _handlers = handler ? _handlers.filter(function (h) { - return h !== handler; - }) : []; + /** + * Mouse events input + * @constructor + * @extends Input + */ + function MouseInput() { + this.evEl = MOUSE_ELEMENT_EVENTS; + this.evWin = MOUSE_WINDOW_EVENTS; - if (_handlers.length > 0) { - hammer._handlers[event] = _handlers; - } - else { - // remove static, propagated handler - hammer._off(event, propagatedHandler); - delete hammer._handlers[event]; - } - } - }); + this.allow = true; // used by Input.TouchMouse to disable mouse events + this.pressed = false; // mousedown state - return hammer; - }; + Input.apply(this, arguments); + } + inherit(MouseInput, Input, { /** - * Emit to the event listeners - * @param {string} eventType - * @param {Event} event + * handle mouse events + * @param {Object} ev */ - hammer.emit = function(eventType, event) { - _firstTarget = event.target; - hammer._emit(eventType, event); - }; - - hammer.destroy = function () { - // Detach from DOM element - var element = hammer.element; - delete element.hammer; - - // clear all handlers - hammer._handlers = {}; - - // call original hammer destroy - hammer._destroy(); - }; - - // split a string with space separated words - function split(events) { - return events.match(/[^ ]+/g); - } + handler: function MEhandler(ev) { + var eventType = MOUSE_INPUT_MAP[ev.type]; - /** - * A static event handler, applying event propagation. - * @param {Object} event - */ - function propagatedHandler(event) { - // let only a single hammer instance handle this event - if (event.type !== 'hammer.input') { - if (event.srcEvent._handled && event.srcEvent._handled[event.type]) { - return; - } - else { - // it is possible that the same srcEvent is used with multiple hammer events - event.srcEvent._handled = {}; - event.srcEvent._handled[event.type] = true; + // on start we want to have the left mouse button down + if (eventType & INPUT_START && ev.button === 0) { + this.pressed = true; } - } - // attach a stopPropagation function to the event - var stopped = false; - event.stopPropagation = function () { - stopped = true; - }; + if (eventType & INPUT_MOVE && ev.which !== 1) { + eventType = INPUT_END; + } - // attach firstTarget property to the event - event.firstTarget = _firstTarget; + // mouse must be down, and mouse events are allowed (see the TouchMouse input) + if (!this.pressed || !this.allow) { + return; + } - // propagate over all elements (until stopped) - var elem = _firstTarget; - while (elem && !stopped) { - var _handlers = elem.hammer && elem.hammer._handlers[event.type]; - if (_handlers) { - for (var i = 0; i < _handlers.length && !stopped; i++) { - _handlers[i](event); - } + if (eventType & INPUT_END) { + this.pressed = false; } - elem = elem.parentNode; - } + this.callback(this.manager, eventType, { + pointers: [ev], + changedPointers: [ev], + pointerType: INPUT_TYPE_MOUSE, + srcEvent: ev + }); } + }); - return hammer; - }; - })); - - -/***/ }, -/* 70 */ -/***/ function(module, exports, __webpack_require__) { - - var __WEBPACK_AMD_DEFINE_RESULT__;/*! Hammer.JS - v2.0.4 - 2014-09-28 - * http://hammerjs.github.io/ - * - * Copyright (c) 2014 Jorik Tangelder; - * Licensed under the MIT license */ - (function(window, document, exportName, undefined) { - 'use strict'; - - var VENDOR_PREFIXES = ['', 'webkit', 'moz', 'MS', 'ms', 'o']; - var TEST_ELEMENT = document.createElement('div'); + var POINTER_INPUT_MAP = { + pointerdown: INPUT_START, + pointermove: INPUT_MOVE, + pointerup: INPUT_END, + pointercancel: INPUT_CANCEL, + pointerout: INPUT_CANCEL + }; - var TYPE_FUNCTION = 'function'; + // in IE10 the pointer types is defined as an enum + var IE10_POINTER_TYPE_ENUM = { + 2: INPUT_TYPE_TOUCH, + 3: INPUT_TYPE_PEN, + 4: INPUT_TYPE_MOUSE, + 5: INPUT_TYPE_KINECT // see https://twitter.com/jacobrossi/status/480596438489890816 + }; - var round = Math.round; - var abs = Math.abs; - var now = Date.now; + var POINTER_ELEMENT_EVENTS = 'pointerdown'; + var POINTER_WINDOW_EVENTS = 'pointermove pointerup pointercancel'; - /** - * set a timeout with a given scope - * @param {Function} fn - * @param {Number} timeout - * @param {Object} context - * @returns {number} - */ - function setTimeoutContext(fn, timeout, context) { - return setTimeout(bindFn(fn, context), timeout); + // IE10 has prefixed support, and case-sensitive + if (window.MSPointerEvent) { + POINTER_ELEMENT_EVENTS = 'MSPointerDown'; + POINTER_WINDOW_EVENTS = 'MSPointerMove MSPointerUp MSPointerCancel'; } /** - * if the argument is an array, we want to execute the fn on each entry - * if it aint an array we don't want to do a thing. - * this is used by all the methods that accept a single and array argument. - * @param {*|Array} arg - * @param {String} fn - * @param {Object} [context] - * @returns {Boolean} + * Pointer events input + * @constructor + * @extends Input */ - function invokeArrayArg(arg, fn, context) { - if (Array.isArray(arg)) { - each(arg, context[fn], context); - return true; - } - return false; + function PointerEventInput() { + this.evEl = POINTER_ELEMENT_EVENTS; + this.evWin = POINTER_WINDOW_EVENTS; + + Input.apply(this, arguments); + + this.store = (this.manager.session.pointerEvents = []); } - /** - * walk objects and arrays - * @param {Object} obj - * @param {Function} iterator - * @param {Object} context - */ - function each(obj, iterator, context) { - var i; + inherit(PointerEventInput, Input, { + /** + * handle mouse events + * @param {Object} ev + */ + handler: function PEhandler(ev) { + var store = this.store; + var removePointer = false; - if (!obj) { - return; - } + var eventTypeNormalized = ev.type.toLowerCase().replace('ms', ''); + var eventType = POINTER_INPUT_MAP[eventTypeNormalized]; + var pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType; - if (obj.forEach) { - obj.forEach(iterator, context); - } else if (obj.length !== undefined) { - i = 0; - while (i < obj.length) { - iterator.call(context, obj[i], i, obj); - i++; - } - } else { - for (i in obj) { - obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj); - } - } - } + var isTouch = (pointerType == INPUT_TYPE_TOUCH); - /** - * extend object. - * means that properties in dest will be overwritten by the ones in src. - * @param {Object} dest - * @param {Object} src - * @param {Boolean} [merge] - * @returns {Object} dest - */ - function extend(dest, src, merge) { - var keys = Object.keys(src); - var i = 0; - while (i < keys.length) { - if (!merge || (merge && dest[keys[i]] === undefined)) { - dest[keys[i]] = src[keys[i]]; + // get index of the event in the store + var storeIndex = inArray(store, ev.pointerId, 'pointerId'); + + // start and mouse must be down + if (eventType & INPUT_START && (ev.button === 0 || isTouch)) { + if (storeIndex < 0) { + store.push(ev); + storeIndex = store.length - 1; + } + } else if (eventType & (INPUT_END | INPUT_CANCEL)) { + removePointer = true; } - i++; - } - return dest; - } - /** - * merge the values from src in the dest. - * means that properties that exist in dest will not be overwritten by src - * @param {Object} dest - * @param {Object} src - * @returns {Object} dest - */ - function merge(dest, src) { - return extend(dest, src, true); - } + // it not found, so the pointer hasn't been down (so it's probably a hover) + if (storeIndex < 0) { + return; + } - /** - * simple class inheritance - * @param {Function} child - * @param {Function} base - * @param {Object} [properties] - */ - function inherit(child, base, properties) { - var baseP = base.prototype, - childP; + // update the event in the store + store[storeIndex] = ev; - childP = child.prototype = Object.create(baseP); - childP.constructor = child; - childP._super = baseP; + this.callback(this.manager, eventType, { + pointers: store, + changedPointers: [ev], + pointerType: pointerType, + srcEvent: ev + }); - if (properties) { - extend(childP, properties); + if (removePointer) { + // remove from the store + store.splice(storeIndex, 1); + } } - } + }); - /** - * simple function bind - * @param {Function} fn - * @param {Object} context - * @returns {Function} - */ - function bindFn(fn, context) { - return function boundFn() { - return fn.apply(context, arguments); - }; - } + var SINGLE_TOUCH_INPUT_MAP = { + touchstart: INPUT_START, + touchmove: INPUT_MOVE, + touchend: INPUT_END, + touchcancel: INPUT_CANCEL + }; - /** - * let a boolean value also be a function that must return a boolean - * this first item in args will be used as the context - * @param {Boolean|Function} val - * @param {Array} [args] - * @returns {Boolean} - */ - function boolOrFn(val, args) { - if (typeof val == TYPE_FUNCTION) { - return val.apply(args ? args[0] || undefined : undefined, args); - } - return val; - } + var SINGLE_TOUCH_TARGET_EVENTS = 'touchstart'; + var SINGLE_TOUCH_WINDOW_EVENTS = 'touchstart touchmove touchend touchcancel'; /** - * use the val2 when val1 is undefined - * @param {*} val1 - * @param {*} val2 - * @returns {*} + * Touch events input + * @constructor + * @extends Input */ - function ifUndefined(val1, val2) { - return (val1 === undefined) ? val2 : val1; - } + function SingleTouchInput() { + this.evTarget = SINGLE_TOUCH_TARGET_EVENTS; + this.evWin = SINGLE_TOUCH_WINDOW_EVENTS; + this.started = false; - /** - * addEventListener with multiple events at once - * @param {EventTarget} target - * @param {String} types - * @param {Function} handler - */ - function addEventListeners(target, types, handler) { - each(splitStr(types), function(type) { - target.addEventListener(type, handler, false); - }); + Input.apply(this, arguments); } - /** - * removeEventListener with multiple events at once - * @param {EventTarget} target - * @param {String} types - * @param {Function} handler - */ - function removeEventListeners(target, types, handler) { - each(splitStr(types), function(type) { - target.removeEventListener(type, handler, false); - }); - } + inherit(SingleTouchInput, Input, { + handler: function TEhandler(ev) { + var type = SINGLE_TOUCH_INPUT_MAP[ev.type]; - /** - * find if a node is in the given parent - * @method hasParent - * @param {HTMLElement} node - * @param {HTMLElement} parent - * @return {Boolean} found - */ - function hasParent(node, parent) { - while (node) { - if (node == parent) { - return true; + // should we handle the touch events? + if (type === INPUT_START) { + this.started = true; } - node = node.parentNode; + + if (!this.started) { + return; + } + + var touches = normalizeSingleTouches.call(this, ev, type); + + // when done, reset the started state + if (type & (INPUT_END | INPUT_CANCEL) && touches[0].length - touches[1].length === 0) { + this.started = false; + } + + this.callback(this.manager, type, { + pointers: touches[0], + changedPointers: touches[1], + pointerType: INPUT_TYPE_TOUCH, + srcEvent: ev + }); } - return false; - } + }); /** - * small indexOf wrapper - * @param {String} str - * @param {String} find - * @returns {Boolean} found + * @this {TouchInput} + * @param {Object} ev + * @param {Number} type flag + * @returns {undefined|Array} [all, changed] */ - function inStr(str, find) { - return str.indexOf(find) > -1; + function normalizeSingleTouches(ev, type) { + var all = toArray(ev.touches); + var changed = toArray(ev.changedTouches); + + if (type & (INPUT_END | INPUT_CANCEL)) { + all = uniqueArray(all.concat(changed), 'identifier', true); + } + + return [all, changed]; } + var TOUCH_INPUT_MAP = { + touchstart: INPUT_START, + touchmove: INPUT_MOVE, + touchend: INPUT_END, + touchcancel: INPUT_CANCEL + }; + + var TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel'; + /** - * split string on whitespace - * @param {String} str - * @returns {Array} words + * Multi-user touch events input + * @constructor + * @extends Input */ - function splitStr(str) { - return str.trim().split(/\s+/g); + function TouchInput() { + this.evTarget = TOUCH_TARGET_EVENTS; + this.targetIds = {}; + + Input.apply(this, arguments); } - /** - * find if a array contains the object using indexOf or a simple polyFill - * @param {Array} src - * @param {String} find - * @param {String} [findByKey] - * @return {Boolean|Number} false when not found, or the index - */ - function inArray(src, find, findByKey) { - if (src.indexOf && !findByKey) { - return src.indexOf(find); - } else { - var i = 0; - while (i < src.length) { - if ((findByKey && src[i][findByKey] == find) || (!findByKey && src[i] === find)) { - return i; - } - i++; + inherit(TouchInput, Input, { + handler: function MTEhandler(ev) { + var type = TOUCH_INPUT_MAP[ev.type]; + var touches = getTouches.call(this, ev, type); + if (!touches) { + return; } - return -1; - } - } - /** - * convert array-like objects to real arrays - * @param {Object} obj - * @returns {Array} - */ - function toArray(obj) { - return Array.prototype.slice.call(obj, 0); - } + this.callback(this.manager, type, { + pointers: touches[0], + changedPointers: touches[1], + pointerType: INPUT_TYPE_TOUCH, + srcEvent: ev + }); + } + }); /** - * unique array with objects based on a key (like 'id') or just by the array's value - * @param {Array} src [{id:1},{id:2},{id:1}] - * @param {String} [key] - * @param {Boolean} [sort=False] - * @returns {Array} [{id:1},{id:2}] + * @this {TouchInput} + * @param {Object} ev + * @param {Number} type flag + * @returns {undefined|Array} [all, changed] */ - function uniqueArray(src, key, sort) { - var results = []; - var values = []; - var i = 0; + function getTouches(ev, type) { + var allTouches = toArray(ev.touches); + var targetIds = this.targetIds; - while (i < src.length) { - var val = key ? src[i][key] : src[i]; - if (inArray(values, val) < 0) { - results.push(src[i]); - } - values[i] = val; - i++; + // when there is only one touch, the process can be simplified + if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) { + targetIds[allTouches[0].identifier] = true; + return [allTouches, allTouches]; } - if (sort) { - if (!key) { - results = results.sort(); - } else { - results = results.sort(function sortUniqueArray(a, b) { - return a[key] > b[key]; - }); - } - } + var i, + targetTouches, + changedTouches = toArray(ev.changedTouches), + changedTargetTouches = [], + target = this.target; - return results; - } + // get target touches from touches + targetTouches = allTouches.filter(function(touch) { + return hasParent(touch.target, target); + }); - /** - * get the prefixed property - * @param {Object} obj - * @param {String} property - * @returns {String|Undefined} prefixed - */ - function prefixed(obj, property) { - var prefix, prop; - var camelProp = property[0].toUpperCase() + property.slice(1); + // collect touches + if (type === INPUT_START) { + i = 0; + while (i < targetTouches.length) { + targetIds[targetTouches[i].identifier] = true; + i++; + } + } - var i = 0; - while (i < VENDOR_PREFIXES.length) { - prefix = VENDOR_PREFIXES[i]; - prop = (prefix) ? prefix + camelProp : property; + // filter changed touches to only contain touches that exist in the collected target ids + i = 0; + while (i < changedTouches.length) { + if (targetIds[changedTouches[i].identifier]) { + changedTargetTouches.push(changedTouches[i]); + } - if (prop in obj) { - return prop; + // cleanup removed touches + if (type & (INPUT_END | INPUT_CANCEL)) { + delete targetIds[changedTouches[i].identifier]; } i++; } - return undefined; - } - /** - * get a unique id - * @returns {number} uniqueId - */ - var _uniqueId = 1; - function uniqueId() { - return _uniqueId++; + if (!changedTargetTouches.length) { + return; + } + + return [ + // merge targetTouches with changedTargetTouches so it contains ALL touches, including 'end' and 'cancel' + uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true), + changedTargetTouches + ]; } /** - * get the window object of an element - * @param {HTMLElement} element - * @returns {DocumentView|Window} + * Combined touch and mouse input + * + * Touch has a higher priority then mouse, and while touching no mouse events are allowed. + * This because touch devices also emit mouse events while doing a touch. + * + * @constructor + * @extends Input */ - function getWindowForElement(element) { - var doc = element.ownerDocument; - return (doc.defaultView || doc.parentWindow); - } - - var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i; + function TouchMouseInput() { + Input.apply(this, arguments); - var SUPPORT_TOUCH = ('ontouchstart' in window); - var SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined; - var SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent); + var handler = bindFn(this.handler, this); + this.touch = new TouchInput(this.manager, handler); + this.mouse = new MouseInput(this.manager, handler); + } - var INPUT_TYPE_TOUCH = 'touch'; - var INPUT_TYPE_PEN = 'pen'; - var INPUT_TYPE_MOUSE = 'mouse'; - var INPUT_TYPE_KINECT = 'kinect'; + inherit(TouchMouseInput, Input, { + /** + * handle mouse and touch events + * @param {Hammer} manager + * @param {String} inputEvent + * @param {Object} inputData + */ + handler: function TMEhandler(manager, inputEvent, inputData) { + var isTouch = (inputData.pointerType == INPUT_TYPE_TOUCH), + isMouse = (inputData.pointerType == INPUT_TYPE_MOUSE); - var COMPUTE_INTERVAL = 25; + // when we're in a touch event, so block all upcoming mouse events + // most mobile browser also emit mouseevents, right after touchstart + if (isTouch) { + this.mouse.allow = false; + } else if (isMouse && !this.mouse.allow) { + return; + } - var INPUT_START = 1; - var INPUT_MOVE = 2; - var INPUT_END = 4; - var INPUT_CANCEL = 8; + // reset the allowMouse when we're done + if (inputEvent & (INPUT_END | INPUT_CANCEL)) { + this.mouse.allow = true; + } - var DIRECTION_NONE = 1; - var DIRECTION_LEFT = 2; - var DIRECTION_RIGHT = 4; - var DIRECTION_UP = 8; - var DIRECTION_DOWN = 16; + this.callback(manager, inputEvent, inputData); + }, - var DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT; - var DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN; - var DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL; + /** + * remove the event listeners + */ + destroy: function destroy() { + this.touch.destroy(); + this.mouse.destroy(); + } + }); - var PROPS_XY = ['x', 'y']; - var PROPS_CLIENT_XY = ['clientX', 'clientY']; + var PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction'); + var NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined; + + // magical touchAction value + var TOUCH_ACTION_COMPUTE = 'compute'; + var TOUCH_ACTION_AUTO = 'auto'; + var TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented + var TOUCH_ACTION_NONE = 'none'; + var TOUCH_ACTION_PAN_X = 'pan-x'; + var TOUCH_ACTION_PAN_Y = 'pan-y'; /** - * create new input type manager + * Touch Action + * sets the touchAction property or uses the js alternative * @param {Manager} manager - * @param {Function} callback - * @returns {Input} + * @param {String} value * @constructor */ - function Input(manager, callback) { - var self = this; + function TouchAction(manager, value) { this.manager = manager; - this.callback = callback; - this.element = manager.element; - this.target = manager.options.inputTarget; + this.set(value); + } - // smaller wrapper around the handler, for the scope and the enabled state of the manager, - // so when disabled the input events are completely bypassed. - this.domHandler = function(ev) { - if (boolOrFn(manager.options.enable, [manager])) { - self.handler(ev); + TouchAction.prototype = { + /** + * set the touchAction value on the element or enable the polyfill + * @param {String} value + */ + set: function(value) { + // find out the touch-action by the event handlers + if (value == TOUCH_ACTION_COMPUTE) { + value = this.compute(); } - }; - this.init(); + if (NATIVE_TOUCH_ACTION) { + this.manager.element.style[PREFIXED_TOUCH_ACTION] = value; + } + this.actions = value.toLowerCase().trim(); + }, - } + /** + * just re-set the touchAction value + */ + update: function() { + this.set(this.manager.options.touchAction); + }, - Input.prototype = { /** - * should handle the inputEvent data and trigger the callback - * @virtual + * compute the value for the touchAction property based on the recognizer's settings + * @returns {String} value */ - handler: function() { }, + compute: function() { + var actions = []; + each(this.manager.recognizers, function(recognizer) { + if (boolOrFn(recognizer.options.enable, [recognizer])) { + actions = actions.concat(recognizer.getTouchAction()); + } + }); + return cleanTouchActions(actions.join(' ')); + }, /** - * bind the events + * this method is called on each input cycle and provides the preventing of the browser behavior + * @param {Object} input */ - init: function() { - this.evEl && addEventListeners(this.element, this.evEl, this.domHandler); - this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler); - this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); + preventDefaults: function(input) { + // not needed with native support for the touchAction property + if (NATIVE_TOUCH_ACTION) { + return; + } + + var srcEvent = input.srcEvent; + var direction = input.offsetDirection; + + // if the touch action did prevented once this session + if (this.manager.session.prevented) { + srcEvent.preventDefault(); + return; + } + + var actions = this.actions; + var hasNone = inStr(actions, TOUCH_ACTION_NONE); + var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y); + var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X); + + if (hasNone || + (hasPanY && direction & DIRECTION_HORIZONTAL) || + (hasPanX && direction & DIRECTION_VERTICAL)) { + return this.preventSrc(srcEvent); + } }, /** - * unbind the events + * call preventDefault to prevent the browser's default behavior (scrolling in most cases) + * @param {Object} srcEvent */ - destroy: function() { - this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler); - this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler); - this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); + preventSrc: function(srcEvent) { + this.manager.session.prevented = true; + srcEvent.preventDefault(); } }; /** - * create new input type manager - * called by the Manager constructor - * @param {Hammer} manager - * @returns {Input} + * when the touchActions are collected they are not a valid value, so we need to clean things up. * + * @param {String} actions + * @returns {*} */ - function createInputInstance(manager) { - var Type; - var inputClass = manager.options.inputClass; - - if (inputClass) { - Type = inputClass; - } else if (SUPPORT_POINTER_EVENTS) { - Type = PointerEventInput; - } else if (SUPPORT_ONLY_TOUCH) { - Type = TouchInput; - } else if (!SUPPORT_TOUCH) { - Type = MouseInput; - } else { - Type = TouchMouseInput; + function cleanTouchActions(actions) { + // none + if (inStr(actions, TOUCH_ACTION_NONE)) { + return TOUCH_ACTION_NONE; } - return new (Type)(manager, inputHandler); - } - - /** - * handle input events - * @param {Manager} manager - * @param {String} eventType - * @param {Object} input - */ - function inputHandler(manager, eventType, input) { - var pointersLen = input.pointers.length; - var changedPointersLen = input.changedPointers.length; - var isFirst = (eventType & INPUT_START && (pointersLen - changedPointersLen === 0)); - var isFinal = (eventType & (INPUT_END | INPUT_CANCEL) && (pointersLen - changedPointersLen === 0)); - input.isFirst = !!isFirst; - input.isFinal = !!isFinal; + var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X); + var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y); - if (isFirst) { - manager.session = {}; + // pan-x and pan-y can be combined + if (hasPanX && hasPanY) { + return TOUCH_ACTION_PAN_X + ' ' + TOUCH_ACTION_PAN_Y; } - // source event is the normalized value of the domEvents - // like 'touchstart, mouseup, pointerdown' - input.eventType = eventType; - - // compute scale, rotation etc - computeInputData(manager, input); + // pan-x OR pan-y + if (hasPanX || hasPanY) { + return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y; + } - // emit secret event - manager.emit('hammer.input', input); + // manipulation + if (inStr(actions, TOUCH_ACTION_MANIPULATION)) { + return TOUCH_ACTION_MANIPULATION; + } - manager.recognize(input); - manager.session.prevInput = input; + return TOUCH_ACTION_AUTO; } /** - * extend the data with some usable properties like scale, rotate, velocity etc - * @param {Object} manager - * @param {Object} input + * Recognizer flow explained; * + * All recognizers have the initial state of POSSIBLE when a input session starts. + * The definition of a input session is from the first input until the last input, with all it's movement in it. * + * Example session for mouse-input: mousedown -> mousemove -> mouseup + * + * On each recognizing cycle (see Manager.recognize) the .recognize() method is executed + * which determines with state it should be. + * + * If the recognizer has the state FAILED, CANCELLED or RECOGNIZED (equals ENDED), it is reset to + * POSSIBLE to give it another change on the next cycle. + * + * Possible + * | + * +-----+---------------+ + * | | + * +-----+-----+ | + * | | | + * Failed Cancelled | + * +-------+------+ + * | | + * Recognized Began + * | + * Changed + * | + * Ended/Recognized */ - function computeInputData(manager, input) { - var session = manager.session; - var pointers = input.pointers; - var pointersLength = pointers.length; + var STATE_POSSIBLE = 1; + var STATE_BEGAN = 2; + var STATE_CHANGED = 4; + var STATE_ENDED = 8; + var STATE_RECOGNIZED = STATE_ENDED; + var STATE_CANCELLED = 16; + var STATE_FAILED = 32; - // store the first input to calculate the distance and direction - if (!session.firstInput) { - session.firstInput = simpleCloneInputData(input); - } + /** + * Recognizer + * Every recognizer needs to extend from this class. + * @constructor + * @param {Object} options + */ + function Recognizer(options) { + this.id = uniqueId(); - // to compute scale and rotation we need to store the multiple touches - if (pointersLength > 1 && !session.firstMultiple) { - session.firstMultiple = simpleCloneInputData(input); - } else if (pointersLength === 1) { - session.firstMultiple = false; - } + this.manager = null; + this.options = merge(options || {}, this.defaults); - var firstInput = session.firstInput; - var firstMultiple = session.firstMultiple; - var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center; + // default is enable true + this.options.enable = ifUndefined(this.options.enable, true); + + this.state = STATE_POSSIBLE; + + this.simultaneous = {}; + this.requireFail = []; + } + + Recognizer.prototype = { + /** + * @virtual + * @type {Object} + */ + defaults: {}, + + /** + * set options + * @param {Object} options + * @return {Recognizer} + */ + set: function(options) { + extend(this.options, options); - var center = input.center = getCenter(pointers); - input.timeStamp = now(); - input.deltaTime = input.timeStamp - firstInput.timeStamp; + // also update the touchAction, in case something changed about the directions/enabled state + this.manager && this.manager.touchAction.update(); + return this; + }, - input.angle = getAngle(offsetCenter, center); - input.distance = getDistance(offsetCenter, center); + /** + * recognize simultaneous with an other recognizer. + * @param {Recognizer} otherRecognizer + * @returns {Recognizer} this + */ + recognizeWith: function(otherRecognizer) { + if (invokeArrayArg(otherRecognizer, 'recognizeWith', this)) { + return this; + } - computeDeltaXY(session, input); - input.offsetDirection = getDirection(input.deltaX, input.deltaY); + var simultaneous = this.simultaneous; + otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); + if (!simultaneous[otherRecognizer.id]) { + simultaneous[otherRecognizer.id] = otherRecognizer; + otherRecognizer.recognizeWith(this); + } + return this; + }, - input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1; - input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0; + /** + * drop the simultaneous link. it doesnt remove the link on the other recognizer. + * @param {Recognizer} otherRecognizer + * @returns {Recognizer} this + */ + dropRecognizeWith: function(otherRecognizer) { + if (invokeArrayArg(otherRecognizer, 'dropRecognizeWith', this)) { + return this; + } - computeIntervalInputData(session, input); + otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); + delete this.simultaneous[otherRecognizer.id]; + return this; + }, - // find the correct target - var target = manager.element; - if (hasParent(input.srcEvent.target, target)) { - target = input.srcEvent.target; - } - input.target = target; - } + /** + * recognizer can only run when an other is failing + * @param {Recognizer} otherRecognizer + * @returns {Recognizer} this + */ + requireFailure: function(otherRecognizer) { + if (invokeArrayArg(otherRecognizer, 'requireFailure', this)) { + return this; + } - function computeDeltaXY(session, input) { - var center = input.center; - var offset = session.offsetDelta || {}; - var prevDelta = session.prevDelta || {}; - var prevInput = session.prevInput || {}; + var requireFail = this.requireFail; + otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); + if (inArray(requireFail, otherRecognizer) === -1) { + requireFail.push(otherRecognizer); + otherRecognizer.requireFailure(this); + } + return this; + }, - if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) { - prevDelta = session.prevDelta = { - x: prevInput.deltaX || 0, - y: prevInput.deltaY || 0 - }; + /** + * drop the requireFailure link. it does not remove the link on the other recognizer. + * @param {Recognizer} otherRecognizer + * @returns {Recognizer} this + */ + dropRequireFailure: function(otherRecognizer) { + if (invokeArrayArg(otherRecognizer, 'dropRequireFailure', this)) { + return this; + } - offset = session.offsetDelta = { - x: center.x, - y: center.y - }; - } + otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); + var index = inArray(this.requireFail, otherRecognizer); + if (index > -1) { + this.requireFail.splice(index, 1); + } + return this; + }, - input.deltaX = prevDelta.x + (center.x - offset.x); - input.deltaY = prevDelta.y + (center.y - offset.y); - } + /** + * has require failures boolean + * @returns {boolean} + */ + hasRequireFailures: function() { + return this.requireFail.length > 0; + }, - /** - * velocity is calculated every x ms - * @param {Object} session - * @param {Object} input - */ - function computeIntervalInputData(session, input) { - var last = session.lastInterval || input, - deltaTime = input.timeStamp - last.timeStamp, - velocity, velocityX, velocityY, direction; + /** + * if the recognizer can recognize simultaneous with an other recognizer + * @param {Recognizer} otherRecognizer + * @returns {Boolean} + */ + canRecognizeWith: function(otherRecognizer) { + return !!this.simultaneous[otherRecognizer.id]; + }, - if (input.eventType != INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) { - var deltaX = last.deltaX - input.deltaX; - var deltaY = last.deltaY - input.deltaY; + /** + * You should use `tryEmit` instead of `emit` directly to check + * that all the needed recognizers has failed before emitting. + * @param {Object} input + */ + emit: function(input) { + var self = this; + var state = this.state; - var v = getVelocity(deltaTime, deltaX, deltaY); - velocityX = v.x; - velocityY = v.y; - velocity = (abs(v.x) > abs(v.y)) ? v.x : v.y; - direction = getDirection(deltaX, deltaY); + function emit(withState) { + self.manager.emit(self.options.event + (withState ? stateStr(state) : ''), input); + } - session.lastInterval = input; - } else { - // use latest velocity info if it doesn't overtake a minimum period - velocity = last.velocity; - velocityX = last.velocityX; - velocityY = last.velocityY; - direction = last.direction; - } + // 'panstart' and 'panmove' + if (state < STATE_ENDED) { + emit(true); + } - input.velocity = velocity; - input.velocityX = velocityX; - input.velocityY = velocityY; - input.direction = direction; - } + emit(); // simple 'eventName' events - /** - * create a simple clone from the input used for storage of firstInput and firstMultiple - * @param {Object} input - * @returns {Object} clonedInputData - */ - function simpleCloneInputData(input) { - // make a simple copy of the pointers because we will get a reference if we don't - // we only need clientXY for the calculations - var pointers = []; - var i = 0; - while (i < input.pointers.length) { - pointers[i] = { - clientX: round(input.pointers[i].clientX), - clientY: round(input.pointers[i].clientY) - }; - i++; - } + // panend and pancancel + if (state >= STATE_ENDED) { + emit(true); + } + }, - return { - timeStamp: now(), - pointers: pointers, - center: getCenter(pointers), - deltaX: input.deltaX, - deltaY: input.deltaY - }; - } + /** + * Check that all the require failure recognizers has failed, + * if true, it emits a gesture event, + * otherwise, setup the state to FAILED. + * @param {Object} input + */ + tryEmit: function(input) { + if (this.canEmit()) { + return this.emit(input); + } + // it's failing anyway + this.state = STATE_FAILED; + }, - /** - * get the center of all the pointers - * @param {Array} pointers - * @return {Object} center contains `x` and `y` properties - */ - function getCenter(pointers) { - var pointersLength = pointers.length; + /** + * can we emit? + * @returns {boolean} + */ + canEmit: function() { + var i = 0; + while (i < this.requireFail.length) { + if (!(this.requireFail[i].state & (STATE_FAILED | STATE_POSSIBLE))) { + return false; + } + i++; + } + return true; + }, - // no need to loop when only one touch - if (pointersLength === 1) { - return { - x: round(pointers[0].clientX), - y: round(pointers[0].clientY) - }; - } + /** + * update the recognizer + * @param {Object} inputData + */ + recognize: function(inputData) { + // make a new copy of the inputData + // so we can change the inputData without messing up the other recognizers + var inputDataClone = extend({}, inputData); - var x = 0, y = 0, i = 0; - while (i < pointersLength) { - x += pointers[i].clientX; - y += pointers[i].clientY; - i++; - } + // is is enabled and allow recognizing? + if (!boolOrFn(this.options.enable, [this, inputDataClone])) { + this.reset(); + this.state = STATE_FAILED; + return; + } - return { - x: round(x / pointersLength), - y: round(y / pointersLength) - }; - } + // reset when we've reached the end + if (this.state & (STATE_RECOGNIZED | STATE_CANCELLED | STATE_FAILED)) { + this.state = STATE_POSSIBLE; + } - /** - * calculate the velocity between two points. unit is in px per ms. - * @param {Number} deltaTime - * @param {Number} x - * @param {Number} y - * @return {Object} velocity `x` and `y` - */ - function getVelocity(deltaTime, x, y) { - return { - x: x / deltaTime || 0, - y: y / deltaTime || 0 - }; - } + this.state = this.process(inputDataClone); - /** - * get the direction between two points - * @param {Number} x - * @param {Number} y - * @return {Number} direction - */ - function getDirection(x, y) { - if (x === y) { - return DIRECTION_NONE; - } + // the recognizer has recognized a gesture + // so trigger an event + if (this.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED | STATE_CANCELLED)) { + this.tryEmit(inputDataClone); + } + }, - if (abs(x) >= abs(y)) { - return x > 0 ? DIRECTION_LEFT : DIRECTION_RIGHT; - } - return y > 0 ? DIRECTION_UP : DIRECTION_DOWN; - } + /** + * return the state of the recognizer + * the actual recognizing happens in this method + * @virtual + * @param {Object} inputData + * @returns {Const} STATE + */ + process: function(inputData) { }, // jshint ignore:line - /** - * calculate the absolute distance between two points - * @param {Object} p1 {x, y} - * @param {Object} p2 {x, y} - * @param {Array} [props] containing x and y keys - * @return {Number} distance - */ - function getDistance(p1, p2, props) { - if (!props) { - props = PROPS_XY; - } - var x = p2[props[0]] - p1[props[0]], - y = p2[props[1]] - p1[props[1]]; + /** + * return the preferred touch-action + * @virtual + * @returns {Array} + */ + getTouchAction: function() { }, - return Math.sqrt((x * x) + (y * y)); - } + /** + * called when the gesture isn't allowed to recognize + * like when another is being recognized or it is disabled + * @virtual + */ + reset: function() { } + }; /** - * calculate the angle between two coordinates - * @param {Object} p1 - * @param {Object} p2 - * @param {Array} [props] containing x and y keys - * @return {Number} angle + * get a usable string, used as event postfix + * @param {Const} state + * @returns {String} state */ - function getAngle(p1, p2, props) { - if (!props) { - props = PROPS_XY; + function stateStr(state) { + if (state & STATE_CANCELLED) { + return 'cancel'; + } else if (state & STATE_ENDED) { + return 'end'; + } else if (state & STATE_CHANGED) { + return 'move'; + } else if (state & STATE_BEGAN) { + return 'start'; } - var x = p2[props[0]] - p1[props[0]], - y = p2[props[1]] - p1[props[1]]; - return Math.atan2(y, x) * 180 / Math.PI; + return ''; } /** - * calculate the rotation degrees between two pointersets - * @param {Array} start array of pointers - * @param {Array} end array of pointers - * @return {Number} rotation + * direction cons to string + * @param {Const} direction + * @returns {String} */ - function getRotation(start, end) { - return getAngle(end[1], end[0], PROPS_CLIENT_XY) - getAngle(start[1], start[0], PROPS_CLIENT_XY); + function directionStr(direction) { + if (direction == DIRECTION_DOWN) { + return 'down'; + } else if (direction == DIRECTION_UP) { + return 'up'; + } else if (direction == DIRECTION_LEFT) { + return 'left'; + } else if (direction == DIRECTION_RIGHT) { + return 'right'; + } + return ''; } /** - * calculate the scale factor between two pointersets - * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out - * @param {Array} start array of pointers - * @param {Array} end array of pointers - * @return {Number} scale + * get a recognizer by name if it is bound to a manager + * @param {Recognizer|String} otherRecognizer + * @param {Recognizer} recognizer + * @returns {Recognizer} */ - function getScale(start, end) { - return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY); + function getRecognizerByNameIfManager(otherRecognizer, recognizer) { + var manager = recognizer.manager; + if (manager) { + return manager.get(otherRecognizer); + } + return otherRecognizer; } - var MOUSE_INPUT_MAP = { - mousedown: INPUT_START, - mousemove: INPUT_MOVE, - mouseup: INPUT_END - }; - - var MOUSE_ELEMENT_EVENTS = 'mousedown'; - var MOUSE_WINDOW_EVENTS = 'mousemove mouseup'; - /** - * Mouse events input + * This recognizer is just used as a base for the simple attribute recognizers. * @constructor - * @extends Input + * @extends Recognizer */ - function MouseInput() { - this.evEl = MOUSE_ELEMENT_EVENTS; - this.evWin = MOUSE_WINDOW_EVENTS; - - this.allow = true; // used by Input.TouchMouse to disable mouse events - this.pressed = false; // mousedown state - - Input.apply(this, arguments); + function AttrRecognizer() { + Recognizer.apply(this, arguments); } - inherit(MouseInput, Input, { + inherit(AttrRecognizer, Recognizer, { /** - * handle mouse events - * @param {Object} ev + * @namespace + * @memberof AttrRecognizer */ - handler: function MEhandler(ev) { - var eventType = MOUSE_INPUT_MAP[ev.type]; - - // on start we want to have the left mouse button down - if (eventType & INPUT_START && ev.button === 0) { - this.pressed = true; - } - - if (eventType & INPUT_MOVE && ev.which !== 1) { - eventType = INPUT_END; - } - - // mouse must be down, and mouse events are allowed (see the TouchMouse input) - if (!this.pressed || !this.allow) { - return; - } - - if (eventType & INPUT_END) { - this.pressed = false; - } - - this.callback(this.manager, eventType, { - pointers: [ev], - changedPointers: [ev], - pointerType: INPUT_TYPE_MOUSE, - srcEvent: ev - }); - } - }); + defaults: { + /** + * @type {Number} + * @default 1 + */ + pointers: 1 + }, - var POINTER_INPUT_MAP = { - pointerdown: INPUT_START, - pointermove: INPUT_MOVE, - pointerup: INPUT_END, - pointercancel: INPUT_CANCEL, - pointerout: INPUT_CANCEL - }; + /** + * Used to check if it the recognizer receives valid input, like input.distance > 10. + * @memberof AttrRecognizer + * @param {Object} input + * @returns {Boolean} recognized + */ + attrTest: function(input) { + var optionPointers = this.options.pointers; + return optionPointers === 0 || input.pointers.length === optionPointers; + }, - // in IE10 the pointer types is defined as an enum - var IE10_POINTER_TYPE_ENUM = { - 2: INPUT_TYPE_TOUCH, - 3: INPUT_TYPE_PEN, - 4: INPUT_TYPE_MOUSE, - 5: INPUT_TYPE_KINECT // see https://twitter.com/jacobrossi/status/480596438489890816 - }; + /** + * Process the input and return the state for the recognizer + * @memberof AttrRecognizer + * @param {Object} input + * @returns {*} State + */ + process: function(input) { + var state = this.state; + var eventType = input.eventType; - var POINTER_ELEMENT_EVENTS = 'pointerdown'; - var POINTER_WINDOW_EVENTS = 'pointermove pointerup pointercancel'; + var isRecognized = state & (STATE_BEGAN | STATE_CHANGED); + var isValid = this.attrTest(input); - // IE10 has prefixed support, and case-sensitive - if (window.MSPointerEvent) { - POINTER_ELEMENT_EVENTS = 'MSPointerDown'; - POINTER_WINDOW_EVENTS = 'MSPointerMove MSPointerUp MSPointerCancel'; - } + // on cancel input and we've recognized before, return STATE_CANCELLED + if (isRecognized && (eventType & INPUT_CANCEL || !isValid)) { + return state | STATE_CANCELLED; + } else if (isRecognized || isValid) { + if (eventType & INPUT_END) { + return state | STATE_ENDED; + } else if (!(state & STATE_BEGAN)) { + return STATE_BEGAN; + } + return state | STATE_CHANGED; + } + return STATE_FAILED; + } + }); /** - * Pointer events input + * Pan + * Recognized when the pointer is down and moved in the allowed direction. * @constructor - * @extends Input + * @extends AttrRecognizer */ - function PointerEventInput() { - this.evEl = POINTER_ELEMENT_EVENTS; - this.evWin = POINTER_WINDOW_EVENTS; - - Input.apply(this, arguments); + function PanRecognizer() { + AttrRecognizer.apply(this, arguments); - this.store = (this.manager.session.pointerEvents = []); + this.pX = null; + this.pY = null; } - inherit(PointerEventInput, Input, { + inherit(PanRecognizer, AttrRecognizer, { /** - * handle mouse events - * @param {Object} ev + * @namespace + * @memberof PanRecognizer */ - handler: function PEhandler(ev) { - var store = this.store; - var removePointer = false; - - var eventTypeNormalized = ev.type.toLowerCase().replace('ms', ''); - var eventType = POINTER_INPUT_MAP[eventTypeNormalized]; - var pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType; + defaults: { + event: 'pan', + threshold: 10, + pointers: 1, + direction: DIRECTION_ALL + }, - var isTouch = (pointerType == INPUT_TYPE_TOUCH); + getTouchAction: function() { + var direction = this.options.direction; + var actions = []; + if (direction & DIRECTION_HORIZONTAL) { + actions.push(TOUCH_ACTION_PAN_Y); + } + if (direction & DIRECTION_VERTICAL) { + actions.push(TOUCH_ACTION_PAN_X); + } + return actions; + }, - // get index of the event in the store - var storeIndex = inArray(store, ev.pointerId, 'pointerId'); + directionTest: function(input) { + var options = this.options; + var hasMoved = true; + var distance = input.distance; + var direction = input.direction; + var x = input.deltaX; + var y = input.deltaY; - // start and mouse must be down - if (eventType & INPUT_START && (ev.button === 0 || isTouch)) { - if (storeIndex < 0) { - store.push(ev); - storeIndex = store.length - 1; + // lock to axis? + if (!(direction & options.direction)) { + if (options.direction & DIRECTION_HORIZONTAL) { + direction = (x === 0) ? DIRECTION_NONE : (x < 0) ? DIRECTION_LEFT : DIRECTION_RIGHT; + hasMoved = x != this.pX; + distance = Math.abs(input.deltaX); + } else { + direction = (y === 0) ? DIRECTION_NONE : (y < 0) ? DIRECTION_UP : DIRECTION_DOWN; + hasMoved = y != this.pY; + distance = Math.abs(input.deltaY); } - } else if (eventType & (INPUT_END | INPUT_CANCEL)) { - removePointer = true; - } - - // it not found, so the pointer hasn't been down (so it's probably a hover) - if (storeIndex < 0) { - return; } + input.direction = direction; + return hasMoved && distance > options.threshold && direction & options.direction; + }, - // update the event in the store - store[storeIndex] = ev; + attrTest: function(input) { + return AttrRecognizer.prototype.attrTest.call(this, input) && + (this.state & STATE_BEGAN || (!(this.state & STATE_BEGAN) && this.directionTest(input))); + }, - this.callback(this.manager, eventType, { - pointers: store, - changedPointers: [ev], - pointerType: pointerType, - srcEvent: ev - }); + emit: function(input) { + this.pX = input.deltaX; + this.pY = input.deltaY; - if (removePointer) { - // remove from the store - store.splice(storeIndex, 1); + var direction = directionStr(input.direction); + if (direction) { + this.manager.emit(this.options.event + direction, input); } + + this._super.emit.call(this, input); } }); - var SINGLE_TOUCH_INPUT_MAP = { - touchstart: INPUT_START, - touchmove: INPUT_MOVE, - touchend: INPUT_END, - touchcancel: INPUT_CANCEL - }; - - var SINGLE_TOUCH_TARGET_EVENTS = 'touchstart'; - var SINGLE_TOUCH_WINDOW_EVENTS = 'touchstart touchmove touchend touchcancel'; - /** - * Touch events input + * Pinch + * Recognized when two or more pointers are moving toward (zoom-in) or away from each other (zoom-out). * @constructor - * @extends Input + * @extends AttrRecognizer */ - function SingleTouchInput() { - this.evTarget = SINGLE_TOUCH_TARGET_EVENTS; - this.evWin = SINGLE_TOUCH_WINDOW_EVENTS; - this.started = false; - - Input.apply(this, arguments); + function PinchRecognizer() { + AttrRecognizer.apply(this, arguments); } - inherit(SingleTouchInput, Input, { - handler: function TEhandler(ev) { - var type = SINGLE_TOUCH_INPUT_MAP[ev.type]; - - // should we handle the touch events? - if (type === INPUT_START) { - this.started = true; - } + inherit(PinchRecognizer, AttrRecognizer, { + /** + * @namespace + * @memberof PinchRecognizer + */ + defaults: { + event: 'pinch', + threshold: 0, + pointers: 2 + }, - if (!this.started) { - return; - } + getTouchAction: function() { + return [TOUCH_ACTION_NONE]; + }, - var touches = normalizeSingleTouches.call(this, ev, type); + attrTest: function(input) { + return this._super.attrTest.call(this, input) && + (Math.abs(input.scale - 1) > this.options.threshold || this.state & STATE_BEGAN); + }, - // when done, reset the started state - if (type & (INPUT_END | INPUT_CANCEL) && touches[0].length - touches[1].length === 0) { - this.started = false; + emit: function(input) { + this._super.emit.call(this, input); + if (input.scale !== 1) { + var inOut = input.scale < 1 ? 'in' : 'out'; + this.manager.emit(this.options.event + inOut, input); } - - this.callback(this.manager, type, { - pointers: touches[0], - changedPointers: touches[1], - pointerType: INPUT_TYPE_TOUCH, - srcEvent: ev - }); } }); /** - * @this {TouchInput} - * @param {Object} ev - * @param {Number} type flag - * @returns {undefined|Array} [all, changed] + * Press + * Recognized when the pointer is down for x ms without any movement. + * @constructor + * @extends Recognizer */ - function normalizeSingleTouches(ev, type) { - var all = toArray(ev.touches); - var changed = toArray(ev.changedTouches); - - if (type & (INPUT_END | INPUT_CANCEL)) { - all = uniqueArray(all.concat(changed), 'identifier', true); - } + function PressRecognizer() { + Recognizer.apply(this, arguments); - return [all, changed]; + this._timer = null; + this._input = null; } - var TOUCH_INPUT_MAP = { - touchstart: INPUT_START, - touchmove: INPUT_MOVE, - touchend: INPUT_END, - touchcancel: INPUT_CANCEL - }; + inherit(PressRecognizer, Recognizer, { + /** + * @namespace + * @memberof PressRecognizer + */ + defaults: { + event: 'press', + pointers: 1, + time: 500, // minimal time of the pointer to be pressed + threshold: 5 // a minimal movement is ok, but keep it low + }, - var TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel'; + getTouchAction: function() { + return [TOUCH_ACTION_AUTO]; + }, + + process: function(input) { + var options = this.options; + var validPointers = input.pointers.length === options.pointers; + var validMovement = input.distance < options.threshold; + var validTime = input.deltaTime > options.time; + + this._input = input; + + // we only allow little movement + // and we've reached an end event, so a tap is possible + if (!validMovement || !validPointers || (input.eventType & (INPUT_END | INPUT_CANCEL) && !validTime)) { + this.reset(); + } else if (input.eventType & INPUT_START) { + this.reset(); + this._timer = setTimeoutContext(function() { + this.state = STATE_RECOGNIZED; + this.tryEmit(); + }, options.time, this); + } else if (input.eventType & INPUT_END) { + return STATE_RECOGNIZED; + } + return STATE_FAILED; + }, + + reset: function() { + clearTimeout(this._timer); + }, + + emit: function(input) { + if (this.state !== STATE_RECOGNIZED) { + return; + } + + if (input && (input.eventType & INPUT_END)) { + this.manager.emit(this.options.event + 'up', input); + } else { + this._input.timeStamp = now(); + this.manager.emit(this.options.event, this._input); + } + } + }); /** - * Multi-user touch events input + * Rotate + * Recognized when two or more pointer are moving in a circular motion. * @constructor - * @extends Input + * @extends AttrRecognizer */ - function TouchInput() { - this.evTarget = TOUCH_TARGET_EVENTS; - this.targetIds = {}; - - Input.apply(this, arguments); + function RotateRecognizer() { + AttrRecognizer.apply(this, arguments); } - inherit(TouchInput, Input, { - handler: function MTEhandler(ev) { - var type = TOUCH_INPUT_MAP[ev.type]; - var touches = getTouches.call(this, ev, type); - if (!touches) { - return; - } + inherit(RotateRecognizer, AttrRecognizer, { + /** + * @namespace + * @memberof RotateRecognizer + */ + defaults: { + event: 'rotate', + threshold: 0, + pointers: 2 + }, - this.callback(this.manager, type, { - pointers: touches[0], - changedPointers: touches[1], - pointerType: INPUT_TYPE_TOUCH, - srcEvent: ev - }); + getTouchAction: function() { + return [TOUCH_ACTION_NONE]; + }, + + attrTest: function(input) { + return this._super.attrTest.call(this, input) && + (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN); } }); /** - * @this {TouchInput} - * @param {Object} ev - * @param {Number} type flag - * @returns {undefined|Array} [all, changed] + * Swipe + * Recognized when the pointer is moving fast (velocity), with enough distance in the allowed direction. + * @constructor + * @extends AttrRecognizer */ - function getTouches(ev, type) { - var allTouches = toArray(ev.touches); - var targetIds = this.targetIds; + function SwipeRecognizer() { + AttrRecognizer.apply(this, arguments); + } - // when there is only one touch, the process can be simplified - if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) { - targetIds[allTouches[0].identifier] = true; - return [allTouches, allTouches]; - } + inherit(SwipeRecognizer, AttrRecognizer, { + /** + * @namespace + * @memberof SwipeRecognizer + */ + defaults: { + event: 'swipe', + threshold: 10, + velocity: 0.65, + direction: DIRECTION_HORIZONTAL | DIRECTION_VERTICAL, + pointers: 1 + }, - var i, - targetTouches, - changedTouches = toArray(ev.changedTouches), - changedTargetTouches = [], - target = this.target; + getTouchAction: function() { + return PanRecognizer.prototype.getTouchAction.call(this); + }, - // get target touches from touches - targetTouches = allTouches.filter(function(touch) { - return hasParent(touch.target, target); - }); + attrTest: function(input) { + var direction = this.options.direction; + var velocity; - // collect touches - if (type === INPUT_START) { - i = 0; - while (i < targetTouches.length) { - targetIds[targetTouches[i].identifier] = true; - i++; + if (direction & (DIRECTION_HORIZONTAL | DIRECTION_VERTICAL)) { + velocity = input.velocity; + } else if (direction & DIRECTION_HORIZONTAL) { + velocity = input.velocityX; + } else if (direction & DIRECTION_VERTICAL) { + velocity = input.velocityY; } - } - // filter changed touches to only contain touches that exist in the collected target ids - i = 0; - while (i < changedTouches.length) { - if (targetIds[changedTouches[i].identifier]) { - changedTargetTouches.push(changedTouches[i]); - } + return this._super.attrTest.call(this, input) && + direction & input.direction && + input.distance > this.options.threshold && + abs(velocity) > this.options.velocity && input.eventType & INPUT_END; + }, - // cleanup removed touches - if (type & (INPUT_END | INPUT_CANCEL)) { - delete targetIds[changedTouches[i].identifier]; + emit: function(input) { + var direction = directionStr(input.direction); + if (direction) { + this.manager.emit(this.options.event + direction, input); } - i++; - } - if (!changedTargetTouches.length) { - return; + this.manager.emit(this.options.event, input); } - - return [ - // merge targetTouches with changedTargetTouches so it contains ALL touches, including 'end' and 'cancel' - uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true), - changedTargetTouches - ]; - } + }); /** - * Combined touch and mouse input - * - * Touch has a higher priority then mouse, and while touching no mouse events are allowed. - * This because touch devices also emit mouse events while doing a touch. + * A tap is ecognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur + * between the given interval and position. The delay option can be used to recognize multi-taps without firing + * a single tap. * + * The eventData from the emitted event contains the property `tapCount`, which contains the amount of + * multi-taps being recognized. * @constructor - * @extends Input + * @extends Recognizer */ - function TouchMouseInput() { - Input.apply(this, arguments); + function TapRecognizer() { + Recognizer.apply(this, arguments); - var handler = bindFn(this.handler, this); - this.touch = new TouchInput(this.manager, handler); - this.mouse = new MouseInput(this.manager, handler); + // previous time and center, + // used for tap counting + this.pTime = false; + this.pCenter = false; + + this._timer = null; + this._input = null; + this.count = 0; } - inherit(TouchMouseInput, Input, { + inherit(TapRecognizer, Recognizer, { /** - * handle mouse and touch events - * @param {Hammer} manager - * @param {String} inputEvent - * @param {Object} inputData + * @namespace + * @memberof PinchRecognizer */ - handler: function TMEhandler(manager, inputEvent, inputData) { - var isTouch = (inputData.pointerType == INPUT_TYPE_TOUCH), - isMouse = (inputData.pointerType == INPUT_TYPE_MOUSE); + defaults: { + event: 'tap', + pointers: 1, + taps: 1, + interval: 300, // max time between the multi-tap taps + time: 250, // max time of the pointer to be down (like finger on the screen) + threshold: 2, // a minimal movement is ok, but keep it low + posThreshold: 10 // a multi-tap can be a bit off the initial position + }, - // when we're in a touch event, so block all upcoming mouse events - // most mobile browser also emit mouseevents, right after touchstart - if (isTouch) { - this.mouse.allow = false; - } else if (isMouse && !this.mouse.allow) { - return; + getTouchAction: function() { + return [TOUCH_ACTION_MANIPULATION]; + }, + + process: function(input) { + var options = this.options; + + var validPointers = input.pointers.length === options.pointers; + var validMovement = input.distance < options.threshold; + var validTouchTime = input.deltaTime < options.time; + + this.reset(); + + if ((input.eventType & INPUT_START) && (this.count === 0)) { + return this.failTimeout(); } - // reset the allowMouse when we're done - if (inputEvent & (INPUT_END | INPUT_CANCEL)) { - this.mouse.allow = true; + // we only allow little movement + // and we've reached an end event, so a tap is possible + if (validMovement && validTouchTime && validPointers) { + if (input.eventType != INPUT_END) { + return this.failTimeout(); + } + + var validInterval = this.pTime ? (input.timeStamp - this.pTime < options.interval) : true; + var validMultiTap = !this.pCenter || getDistance(this.pCenter, input.center) < options.posThreshold; + + this.pTime = input.timeStamp; + this.pCenter = input.center; + + if (!validMultiTap || !validInterval) { + this.count = 1; + } else { + this.count += 1; + } + + this._input = input; + + // if tap count matches we have recognized it, + // else it has began recognizing... + var tapCount = this.count % options.taps; + if (tapCount === 0) { + // no failing requirements, immediately trigger the tap event + // or wait as long as the multitap interval to trigger + if (!this.hasRequireFailures()) { + return STATE_RECOGNIZED; + } else { + this._timer = setTimeoutContext(function() { + this.state = STATE_RECOGNIZED; + this.tryEmit(); + }, options.interval, this); + return STATE_BEGAN; + } + } } + return STATE_FAILED; + }, + + failTimeout: function() { + this._timer = setTimeoutContext(function() { + this.state = STATE_FAILED; + }, this.options.interval, this); + return STATE_FAILED; + }, - this.callback(manager, inputEvent, inputData); + reset: function() { + clearTimeout(this._timer); }, - /** - * remove the event listeners - */ - destroy: function destroy() { - this.touch.destroy(); - this.mouse.destroy(); + emit: function() { + if (this.state == STATE_RECOGNIZED ) { + this._input.tapCount = this.count; + this.manager.emit(this.options.event, this._input); + } } }); - var PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction'); - var NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined; - - // magical touchAction value - var TOUCH_ACTION_COMPUTE = 'compute'; - var TOUCH_ACTION_AUTO = 'auto'; - var TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented - var TOUCH_ACTION_NONE = 'none'; - var TOUCH_ACTION_PAN_X = 'pan-x'; - var TOUCH_ACTION_PAN_Y = 'pan-y'; - /** - * Touch Action - * sets the touchAction property or uses the js alternative - * @param {Manager} manager - * @param {String} value + * Simple way to create an manager with a default set of recognizers. + * @param {HTMLElement} element + * @param {Object} [options] * @constructor */ - function TouchAction(manager, value) { - this.manager = manager; - this.set(value); + function Hammer(element, options) { + options = options || {}; + options.recognizers = ifUndefined(options.recognizers, Hammer.defaults.preset); + return new Manager(element, options); } - TouchAction.prototype = { + /** + * @const {string} + */ + Hammer.VERSION = '2.0.4'; + + /** + * default settings + * @namespace + */ + Hammer.defaults = { /** - * set the touchAction value on the element or enable the polyfill - * @param {String} value + * set if DOM events are being triggered. + * But this is slower and unused by simple implementations, so disabled by default. + * @type {Boolean} + * @default false */ - set: function(value) { - // find out the touch-action by the event handlers - if (value == TOUCH_ACTION_COMPUTE) { - value = this.compute(); - } - - if (NATIVE_TOUCH_ACTION) { - this.manager.element.style[PREFIXED_TOUCH_ACTION] = value; - } - this.actions = value.toLowerCase().trim(); - }, + domEvents: false, /** - * just re-set the touchAction value + * The value for the touchAction property/fallback. + * When set to `compute` it will magically set the correct value based on the added recognizers. + * @type {String} + * @default compute */ - update: function() { - this.set(this.manager.options.touchAction); - }, + touchAction: TOUCH_ACTION_COMPUTE, /** - * compute the value for the touchAction property based on the recognizer's settings - * @returns {String} value + * @type {Boolean} + * @default true */ - compute: function() { - var actions = []; - each(this.manager.recognizers, function(recognizer) { - if (boolOrFn(recognizer.options.enable, [recognizer])) { - actions = actions.concat(recognizer.getTouchAction()); - } - }); - return cleanTouchActions(actions.join(' ')); - }, + enable: true, /** - * this method is called on each input cycle and provides the preventing of the browser behavior - * @param {Object} input + * EXPERIMENTAL FEATURE -- can be removed/changed + * Change the parent input target element. + * If Null, then it is being set the to main element. + * @type {Null|EventTarget} + * @default null */ - preventDefaults: function(input) { - // not needed with native support for the touchAction property - if (NATIVE_TOUCH_ACTION) { - return; - } - - var srcEvent = input.srcEvent; - var direction = input.offsetDirection; - - // if the touch action did prevented once this session - if (this.manager.session.prevented) { - srcEvent.preventDefault(); - return; - } - - var actions = this.actions; - var hasNone = inStr(actions, TOUCH_ACTION_NONE); - var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y); - var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X); - - if (hasNone || - (hasPanY && direction & DIRECTION_HORIZONTAL) || - (hasPanX && direction & DIRECTION_VERTICAL)) { - return this.preventSrc(srcEvent); - } - }, + inputTarget: null, /** - * call preventDefault to prevent the browser's default behavior (scrolling in most cases) - * @param {Object} srcEvent + * force an input class + * @type {Null|Function} + * @default null */ - preventSrc: function(srcEvent) { - this.manager.session.prevented = true; - srcEvent.preventDefault(); - } - }; + inputClass: null, - /** - * when the touchActions are collected they are not a valid value, so we need to clean things up. * - * @param {String} actions - * @returns {*} - */ - function cleanTouchActions(actions) { - // none - if (inStr(actions, TOUCH_ACTION_NONE)) { - return TOUCH_ACTION_NONE; - } + /** + * Default recognizer setup when calling `Hammer()` + * When creating a new Manager these will be skipped. + * @type {Array} + */ + preset: [ + // RecognizerClass, options, [recognizeWith, ...], [requireFailure, ...] + [RotateRecognizer, { enable: false }], + [PinchRecognizer, { enable: false }, ['rotate']], + [SwipeRecognizer,{ direction: DIRECTION_HORIZONTAL }], + [PanRecognizer, { direction: DIRECTION_HORIZONTAL }, ['swipe']], + [TapRecognizer], + [TapRecognizer, { event: 'doubletap', taps: 2 }, ['tap']], + [PressRecognizer] + ], - var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X); - var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y); + /** + * Some CSS properties can be used to improve the working of Hammer. + * Add them to this method and they will be set when creating a new Manager. + * @namespace + */ + cssProps: { + /** + * Disables text selection to improve the dragging gesture. Mainly for desktop browsers. + * @type {String} + * @default 'none' + */ + userSelect: 'none', - // pan-x and pan-y can be combined - if (hasPanX && hasPanY) { - return TOUCH_ACTION_PAN_X + ' ' + TOUCH_ACTION_PAN_Y; - } + /** + * Disable the Windows Phone grippers when pressing an element. + * @type {String} + * @default 'none' + */ + touchSelect: 'none', - // pan-x OR pan-y - if (hasPanX || hasPanY) { - return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y; - } + /** + * Disables the default callout shown when you touch and hold a touch target. + * On iOS, when you touch and hold a touch target such as a link, Safari displays + * a callout containing information about the link. This property allows you to disable that callout. + * @type {String} + * @default 'none' + */ + touchCallout: 'none', - // manipulation - if (inStr(actions, TOUCH_ACTION_MANIPULATION)) { - return TOUCH_ACTION_MANIPULATION; - } + /** + * Specifies whether zooming is enabled. Used by IE10> + * @type {String} + * @default 'none' + */ + contentZooming: 'none', - return TOUCH_ACTION_AUTO; - } + /** + * Specifies that an entire element should be draggable instead of its contents. Mainly for desktop browsers. + * @type {String} + * @default 'none' + */ + userDrag: 'none', - /** - * Recognizer flow explained; * - * All recognizers have the initial state of POSSIBLE when a input session starts. - * The definition of a input session is from the first input until the last input, with all it's movement in it. * - * Example session for mouse-input: mousedown -> mousemove -> mouseup - * - * On each recognizing cycle (see Manager.recognize) the .recognize() method is executed - * which determines with state it should be. - * - * If the recognizer has the state FAILED, CANCELLED or RECOGNIZED (equals ENDED), it is reset to - * POSSIBLE to give it another change on the next cycle. - * - * Possible - * | - * +-----+---------------+ - * | | - * +-----+-----+ | - * | | | - * Failed Cancelled | - * +-------+------+ - * | | - * Recognized Began - * | - * Changed - * | - * Ended/Recognized - */ - var STATE_POSSIBLE = 1; - var STATE_BEGAN = 2; - var STATE_CHANGED = 4; - var STATE_ENDED = 8; - var STATE_RECOGNIZED = STATE_ENDED; - var STATE_CANCELLED = 16; - var STATE_FAILED = 32; + /** + * Overrides the highlight color shown when the user taps a link or a JavaScript + * clickable element in iOS. This property obeys the alpha value, if specified. + * @type {String} + * @default 'rgba(0,0,0,0)' + */ + tapHighlightColor: 'rgba(0,0,0,0)' + } + }; + + var STOP = 1; + var FORCED_STOP = 2; /** - * Recognizer - * Every recognizer needs to extend from this class. + * Manager + * @param {HTMLElement} element + * @param {Object} [options] * @constructor - * @param {Object} options */ - function Recognizer(options) { - this.id = uniqueId(); + function Manager(element, options) { + options = options || {}; - this.manager = null; - this.options = merge(options || {}, this.defaults); + this.options = merge(options, Hammer.defaults); + this.options.inputTarget = this.options.inputTarget || element; - // default is enable true - this.options.enable = ifUndefined(this.options.enable, true); + this.handlers = {}; + this.session = {}; + this.recognizers = []; - this.state = STATE_POSSIBLE; + this.element = element; + this.input = createInputInstance(this); + this.touchAction = new TouchAction(this, this.options.touchAction); - this.simultaneous = {}; - this.requireFail = []; - } + toggleCssProps(this, true); - Recognizer.prototype = { - /** - * @virtual - * @type {Object} - */ - defaults: {}, + each(options.recognizers, function(item) { + var recognizer = this.add(new (item[0])(item[1])); + item[2] && recognizer.recognizeWith(item[2]); + item[3] && recognizer.requireFailure(item[3]); + }, this); + } + Manager.prototype = { /** * set options * @param {Object} options - * @return {Recognizer} + * @returns {Manager} */ set: function(options) { extend(this.options, options); - // also update the touchAction, in case something changed about the directions/enabled state - this.manager && this.manager.touchAction.update(); + // Options that need a little more setup + if (options.touchAction) { + this.touchAction.update(); + } + if (options.inputTarget) { + // Clean up existing event listeners and reinitialize + this.input.destroy(); + this.input.target = options.inputTarget; + this.input.init(); + } return this; }, /** - * recognize simultaneous with an other recognizer. - * @param {Recognizer} otherRecognizer - * @returns {Recognizer} this + * stop recognizing for this session. + * This session will be discarded, when a new [input]start event is fired. + * When forced, the recognizer cycle is stopped immediately. + * @param {Boolean} [force] */ - recognizeWith: function(otherRecognizer) { - if (invokeArrayArg(otherRecognizer, 'recognizeWith', this)) { - return this; - } - - var simultaneous = this.simultaneous; - otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); - if (!simultaneous[otherRecognizer.id]) { - simultaneous[otherRecognizer.id] = otherRecognizer; - otherRecognizer.recognizeWith(this); - } - return this; + stop: function(force) { + this.session.stopped = force ? FORCED_STOP : STOP; }, /** - * drop the simultaneous link. it doesnt remove the link on the other recognizer. - * @param {Recognizer} otherRecognizer - * @returns {Recognizer} this + * run the recognizers! + * called by the inputHandler function on every movement of the pointers (touches) + * it walks through all the recognizers and tries to detect the gesture that is being made + * @param {Object} inputData */ - dropRecognizeWith: function(otherRecognizer) { - if (invokeArrayArg(otherRecognizer, 'dropRecognizeWith', this)) { - return this; + recognize: function(inputData) { + var session = this.session; + if (session.stopped) { + return; } - otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); - delete this.simultaneous[otherRecognizer.id]; - return this; + // run the touch-action polyfill + this.touchAction.preventDefaults(inputData); + + var recognizer; + var recognizers = this.recognizers; + + // this holds the recognizer that is being recognized. + // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED + // if no recognizer is detecting a thing, it is set to `null` + var curRecognizer = session.curRecognizer; + + // reset when the last recognizer is recognized + // or when we're in a new session + if (!curRecognizer || (curRecognizer && curRecognizer.state & STATE_RECOGNIZED)) { + curRecognizer = session.curRecognizer = null; + } + + var i = 0; + while (i < recognizers.length) { + recognizer = recognizers[i]; + + // find out if we are allowed try to recognize the input for this one. + // 1. allow if the session is NOT forced stopped (see the .stop() method) + // 2. allow if we still haven't recognized a gesture in this session, or the this recognizer is the one + // that is being recognized. + // 3. allow if the recognizer is allowed to run simultaneous with the current recognized recognizer. + // this can be setup with the `recognizeWith()` method on the recognizer. + if (session.stopped !== FORCED_STOP && ( // 1 + !curRecognizer || recognizer == curRecognizer || // 2 + recognizer.canRecognizeWith(curRecognizer))) { // 3 + recognizer.recognize(inputData); + } else { + recognizer.reset(); + } + + // if the recognizer has been recognizing the input as a valid gesture, we want to store this one as the + // current active recognizer. but only if we don't already have an active recognizer + if (!curRecognizer && recognizer.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED)) { + curRecognizer = session.curRecognizer = recognizer; + } + i++; + } }, /** - * recognizer can only run when an other is failing - * @param {Recognizer} otherRecognizer - * @returns {Recognizer} this + * get a recognizer by its event name. + * @param {Recognizer|String} recognizer + * @returns {Recognizer|Null} */ - requireFailure: function(otherRecognizer) { - if (invokeArrayArg(otherRecognizer, 'requireFailure', this)) { - return this; + get: function(recognizer) { + if (recognizer instanceof Recognizer) { + return recognizer; } - var requireFail = this.requireFail; - otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); - if (inArray(requireFail, otherRecognizer) === -1) { - requireFail.push(otherRecognizer); - otherRecognizer.requireFailure(this); + var recognizers = this.recognizers; + for (var i = 0; i < recognizers.length; i++) { + if (recognizers[i].options.event == recognizer) { + return recognizers[i]; + } } - return this; + return null; }, /** - * drop the requireFailure link. it does not remove the link on the other recognizer. - * @param {Recognizer} otherRecognizer - * @returns {Recognizer} this + * add a recognizer to the manager + * existing recognizers with the same event name will be removed + * @param {Recognizer} recognizer + * @returns {Recognizer|Manager} */ - dropRequireFailure: function(otherRecognizer) { - if (invokeArrayArg(otherRecognizer, 'dropRequireFailure', this)) { + add: function(recognizer) { + if (invokeArrayArg(recognizer, 'add', this)) { return this; } - otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); - var index = inArray(this.requireFail, otherRecognizer); - if (index > -1) { - this.requireFail.splice(index, 1); + // remove existing + var existing = this.get(recognizer.options.event); + if (existing) { + this.remove(existing); } - return this; - }, - /** - * has require failures boolean - * @returns {boolean} - */ - hasRequireFailures: function() { - return this.requireFail.length > 0; - }, + this.recognizers.push(recognizer); + recognizer.manager = this; - /** - * if the recognizer can recognize simultaneous with an other recognizer - * @param {Recognizer} otherRecognizer - * @returns {Boolean} - */ - canRecognizeWith: function(otherRecognizer) { - return !!this.simultaneous[otherRecognizer.id]; + this.touchAction.update(); + return recognizer; }, /** - * You should use `tryEmit` instead of `emit` directly to check - * that all the needed recognizers has failed before emitting. - * @param {Object} input + * remove a recognizer by name or instance + * @param {Recognizer|String} recognizer + * @returns {Manager} */ - emit: function(input) { - var self = this; - var state = this.state; - - function emit(withState) { - self.manager.emit(self.options.event + (withState ? stateStr(state) : ''), input); - } - - // 'panstart' and 'panmove' - if (state < STATE_ENDED) { - emit(true); + remove: function(recognizer) { + if (invokeArrayArg(recognizer, 'remove', this)) { + return this; } - emit(); // simple 'eventName' events + var recognizers = this.recognizers; + recognizer = this.get(recognizer); + recognizers.splice(inArray(recognizers, recognizer), 1); - // panend and pancancel - if (state >= STATE_ENDED) { - emit(true); - } + this.touchAction.update(); + return this; }, /** - * Check that all the require failure recognizers has failed, - * if true, it emits a gesture event, - * otherwise, setup the state to FAILED. - * @param {Object} input + * bind event + * @param {String} events + * @param {Function} handler + * @returns {EventEmitter} this */ - tryEmit: function(input) { - if (this.canEmit()) { - return this.emit(input); - } - // it's failing anyway - this.state = STATE_FAILED; + on: function(events, handler) { + var handlers = this.handlers; + each(splitStr(events), function(event) { + handlers[event] = handlers[event] || []; + handlers[event].push(handler); + }); + return this; }, /** - * can we emit? - * @returns {boolean} + * unbind event, leave emit blank to remove all handlers + * @param {String} events + * @param {Function} [handler] + * @returns {EventEmitter} this */ - canEmit: function() { - var i = 0; - while (i < this.requireFail.length) { - if (!(this.requireFail[i].state & (STATE_FAILED | STATE_POSSIBLE))) { - return false; + off: function(events, handler) { + var handlers = this.handlers; + each(splitStr(events), function(event) { + if (!handler) { + delete handlers[event]; + } else { + handlers[event].splice(inArray(handlers[event], handler), 1); } - i++; - } - return true; + }); + return this; }, /** - * update the recognizer - * @param {Object} inputData + * emit event to the listeners + * @param {String} event + * @param {Object} data */ - recognize: function(inputData) { - // make a new copy of the inputData - // so we can change the inputData without messing up the other recognizers - var inputDataClone = extend({}, inputData); - - // is is enabled and allow recognizing? - if (!boolOrFn(this.options.enable, [this, inputDataClone])) { - this.reset(); - this.state = STATE_FAILED; - return; + emit: function(event, data) { + // we also want to trigger dom events + if (this.options.domEvents) { + triggerDomEvent(event, data); } - // reset when we've reached the end - if (this.state & (STATE_RECOGNIZED | STATE_CANCELLED | STATE_FAILED)) { - this.state = STATE_POSSIBLE; + // no handlers, so skip it all + var handlers = this.handlers[event] && this.handlers[event].slice(); + if (!handlers || !handlers.length) { + return; } - this.state = this.process(inputDataClone); + data.type = event; + data.preventDefault = function() { + data.srcEvent.preventDefault(); + }; - // the recognizer has recognized a gesture - // so trigger an event - if (this.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED | STATE_CANCELLED)) { - this.tryEmit(inputDataClone); + var i = 0; + while (i < handlers.length) { + handlers[i](data); + i++; } }, /** - * return the state of the recognizer - * the actual recognizing happens in this method - * @virtual - * @param {Object} inputData - * @returns {Const} STATE - */ - process: function(inputData) { }, // jshint ignore:line - - /** - * return the preferred touch-action - * @virtual - * @returns {Array} + * destroy the manager and unbinds all events + * it doesn't unbind dom events, that is the user own responsibility */ - getTouchAction: function() { }, + destroy: function() { + this.element && toggleCssProps(this, false); - /** - * called when the gesture isn't allowed to recognize - * like when another is being recognized or it is disabled - * @virtual - */ - reset: function() { } + this.handlers = {}; + this.session = {}; + this.input.destroy(); + this.element = null; + } }; /** - * get a usable string, used as event postfix - * @param {Const} state - * @returns {String} state + * add/remove the css properties as defined in manager.options.cssProps + * @param {Manager} manager + * @param {Boolean} add */ - function stateStr(state) { - if (state & STATE_CANCELLED) { - return 'cancel'; - } else if (state & STATE_ENDED) { - return 'end'; - } else if (state & STATE_CHANGED) { - return 'move'; - } else if (state & STATE_BEGAN) { - return 'start'; - } - return ''; + function toggleCssProps(manager, add) { + var element = manager.element; + each(manager.options.cssProps, function(value, name) { + element.style[prefixed(element.style, name)] = add ? value : ''; + }); } /** - * direction cons to string - * @param {Const} direction - * @returns {String} + * trigger dom event + * @param {String} event + * @param {Object} data */ - function directionStr(direction) { - if (direction == DIRECTION_DOWN) { - return 'down'; - } else if (direction == DIRECTION_UP) { - return 'up'; - } else if (direction == DIRECTION_LEFT) { - return 'left'; - } else if (direction == DIRECTION_RIGHT) { - return 'right'; - } - return ''; + function triggerDomEvent(event, data) { + var gestureEvent = document.createEvent('Event'); + gestureEvent.initEvent(event, true, true); + gestureEvent.gesture = data; + data.target.dispatchEvent(gestureEvent); } - /** - * get a recognizer by name if it is bound to a manager - * @param {Recognizer|String} otherRecognizer - * @param {Recognizer} recognizer - * @returns {Recognizer} - */ - function getRecognizerByNameIfManager(otherRecognizer, recognizer) { - var manager = recognizer.manager; - if (manager) { - return manager.get(otherRecognizer); - } - return otherRecognizer; - } + extend(Hammer, { + INPUT_START: INPUT_START, + INPUT_MOVE: INPUT_MOVE, + INPUT_END: INPUT_END, + INPUT_CANCEL: INPUT_CANCEL, - /** - * This recognizer is just used as a base for the simple attribute recognizers. - * @constructor - * @extends Recognizer - */ - function AttrRecognizer() { - Recognizer.apply(this, arguments); + STATE_POSSIBLE: STATE_POSSIBLE, + STATE_BEGAN: STATE_BEGAN, + STATE_CHANGED: STATE_CHANGED, + STATE_ENDED: STATE_ENDED, + STATE_RECOGNIZED: STATE_RECOGNIZED, + STATE_CANCELLED: STATE_CANCELLED, + STATE_FAILED: STATE_FAILED, + + DIRECTION_NONE: DIRECTION_NONE, + DIRECTION_LEFT: DIRECTION_LEFT, + DIRECTION_RIGHT: DIRECTION_RIGHT, + DIRECTION_UP: DIRECTION_UP, + DIRECTION_DOWN: DIRECTION_DOWN, + DIRECTION_HORIZONTAL: DIRECTION_HORIZONTAL, + DIRECTION_VERTICAL: DIRECTION_VERTICAL, + DIRECTION_ALL: DIRECTION_ALL, + + Manager: Manager, + Input: Input, + TouchAction: TouchAction, + + TouchInput: TouchInput, + MouseInput: MouseInput, + PointerEventInput: PointerEventInput, + TouchMouseInput: TouchMouseInput, + SingleTouchInput: SingleTouchInput, + + Recognizer: Recognizer, + AttrRecognizer: AttrRecognizer, + Tap: TapRecognizer, + Pan: PanRecognizer, + Swipe: SwipeRecognizer, + Pinch: PinchRecognizer, + Rotate: RotateRecognizer, + Press: PressRecognizer, + + on: addEventListeners, + off: removeEventListeners, + each: each, + merge: merge, + extend: extend, + inherit: inherit, + bindFn: bindFn, + prefixed: prefixed + }); + + if ("function" == TYPE_FUNCTION && __webpack_require__(84)) { + !(__WEBPACK_AMD_DEFINE_RESULT__ = function() { + return Hammer; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + } else if (typeof module != 'undefined' && module.exports) { + module.exports = Hammer; + } else { + window[exportName] = Hammer; } - inherit(AttrRecognizer, Recognizer, { - /** - * @namespace - * @memberof AttrRecognizer - */ - defaults: { - /** - * @type {Number} - * @default 1 - */ - pointers: 1 - }, + })(window, document, 'Hammer'); - /** - * Used to check if it the recognizer receives valid input, like input.distance > 10. - * @memberof AttrRecognizer - * @param {Object} input - * @returns {Boolean} recognized - */ - attrTest: function(input) { - var optionPointers = this.options.pointers; - return optionPointers === 0 || input.pointers.length === optionPointers; - }, - /** - * Process the input and return the state for the recognizer - * @memberof AttrRecognizer - * @param {Object} input - * @returns {*} State - */ - process: function(input) { - var state = this.state; - var eventType = input.eventType; +/***/ }, +/* 67 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; + + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + Object.defineProperty(exports, '__esModule', { + value: true + }); + + var _Label = __webpack_require__(68); + + var _Label2 = _interopRequireWildcard(_Label); + + var _Box = __webpack_require__(90); + + var _Box2 = _interopRequireWildcard(_Box); + + var _Circle = __webpack_require__(91); + + var _Circle2 = _interopRequireWildcard(_Circle); + + var _CircularImage = __webpack_require__(92); + + var _CircularImage2 = _interopRequireWildcard(_CircularImage); + + var _Database = __webpack_require__(93); + + var _Database2 = _interopRequireWildcard(_Database); + + var _Diamond = __webpack_require__(94); + + var _Diamond2 = _interopRequireWildcard(_Diamond); + + var _Dot = __webpack_require__(95); + + var _Dot2 = _interopRequireWildcard(_Dot); + + var _Ellipse = __webpack_require__(96); - var isRecognized = state & (STATE_BEGAN | STATE_CHANGED); - var isValid = this.attrTest(input); + var _Ellipse2 = _interopRequireWildcard(_Ellipse); - // on cancel input and we've recognized before, return STATE_CANCELLED - if (isRecognized && (eventType & INPUT_CANCEL || !isValid)) { - return state | STATE_CANCELLED; - } else if (isRecognized || isValid) { - if (eventType & INPUT_END) { - return state | STATE_ENDED; - } else if (!(state & STATE_BEGAN)) { - return STATE_BEGAN; - } - return state | STATE_CHANGED; - } - return STATE_FAILED; - } - }); + var _Icon = __webpack_require__(97); - /** - * Pan - * Recognized when the pointer is down and moved in the allowed direction. - * @constructor - * @extends AttrRecognizer - */ - function PanRecognizer() { - AttrRecognizer.apply(this, arguments); + var _Icon2 = _interopRequireWildcard(_Icon); - this.pX = null; - this.pY = null; - } + var _Image = __webpack_require__(98); - inherit(PanRecognizer, AttrRecognizer, { - /** - * @namespace - * @memberof PanRecognizer - */ - defaults: { - event: 'pan', - threshold: 10, - pointers: 1, - direction: DIRECTION_ALL - }, + var _Image2 = _interopRequireWildcard(_Image); - getTouchAction: function() { - var direction = this.options.direction; - var actions = []; - if (direction & DIRECTION_HORIZONTAL) { - actions.push(TOUCH_ACTION_PAN_Y); - } - if (direction & DIRECTION_VERTICAL) { - actions.push(TOUCH_ACTION_PAN_X); - } - return actions; - }, + var _Square = __webpack_require__(99); - directionTest: function(input) { - var options = this.options; - var hasMoved = true; - var distance = input.distance; - var direction = input.direction; - var x = input.deltaX; - var y = input.deltaY; + var _Square2 = _interopRequireWildcard(_Square); - // lock to axis? - if (!(direction & options.direction)) { - if (options.direction & DIRECTION_HORIZONTAL) { - direction = (x === 0) ? DIRECTION_NONE : (x < 0) ? DIRECTION_LEFT : DIRECTION_RIGHT; - hasMoved = x != this.pX; - distance = Math.abs(input.deltaX); - } else { - direction = (y === 0) ? DIRECTION_NONE : (y < 0) ? DIRECTION_UP : DIRECTION_DOWN; - hasMoved = y != this.pY; - distance = Math.abs(input.deltaY); - } - } - input.direction = direction; - return hasMoved && distance > options.threshold && direction & options.direction; - }, + var _Star = __webpack_require__(100); - attrTest: function(input) { - return AttrRecognizer.prototype.attrTest.call(this, input) && - (this.state & STATE_BEGAN || (!(this.state & STATE_BEGAN) && this.directionTest(input))); - }, + var _Star2 = _interopRequireWildcard(_Star); - emit: function(input) { - this.pX = input.deltaX; - this.pY = input.deltaY; + var _Text = __webpack_require__(101); - var direction = directionStr(input.direction); - if (direction) { - this.manager.emit(this.options.event + direction, input); - } + var _Text2 = _interopRequireWildcard(_Text); - this._super.emit.call(this, input); - } - }); + var _Triangle = __webpack_require__(102); + + var _Triangle2 = _interopRequireWildcard(_Triangle); + + var _TriangleDown = __webpack_require__(103); + + var _TriangleDown2 = _interopRequireWildcard(_TriangleDown); + + var util = __webpack_require__(1); /** - * Pinch - * Recognized when two or more pointers are moving toward (zoom-in) or away from each other (zoom-out). - * @constructor - * @extends AttrRecognizer + * @class Node + * A node. A node can be connected to other nodes via one or multiple edges. + * @param {object} options An object containing options for the node. All + * options 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 options + * @param {Object} constants An object with default values for + * example for the color + * */ - function PinchRecognizer() { - AttrRecognizer.apply(this, arguments); - } - inherit(PinchRecognizer, AttrRecognizer, { - /** - * @namespace - * @memberof PinchRecognizer - */ - defaults: { - event: 'pinch', - threshold: 0, - pointers: 2 - }, + var Node = (function () { + function Node(options, body, imagelist, grouplist, globalOptions) { + _classCallCheck(this, Node); - getTouchAction: function() { - return [TOUCH_ACTION_NONE]; - }, + this.options = util.bridgeObject(globalOptions); + this.body = body; - attrTest: function(input) { - return this._super.attrTest.call(this, input) && - (Math.abs(input.scale - 1) > this.options.threshold || this.state & STATE_BEGAN); - }, + this.edges = []; // all edges connected to this node - emit: function(input) { - this._super.emit.call(this, input); - if (input.scale !== 1) { - var inOut = input.scale < 1 ? 'in' : 'out'; - this.manager.emit(this.options.event + inOut, input); - } - } - }); + // set defaults for the options + this.id = undefined; + this.imagelist = imagelist; + this.grouplist = grouplist; - /** - * Press - * Recognized when the pointer is down for x ms without any movement. - * @constructor - * @extends Recognizer - */ - function PressRecognizer() { - Recognizer.apply(this, arguments); + // state options + this.x = undefined; + this.y = undefined; + this.predefinedPosition = false; // used to check if initial zoomExtent should just take the range or approximate + this.selected = false; + this.hover = false; - this._timer = null; - this._input = null; - } + this.labelModule = new _Label2['default'](this.body, this.options); + this.setOptions(options); + } + + _createClass(Node, [{ + key: 'attachEdge', - inherit(PressRecognizer, Recognizer, { /** - * @namespace - * @memberof PressRecognizer + * Attach a edge to the node + * @param {Edge} edge */ - defaults: { - event: 'press', - pointers: 1, - time: 500, // minimal time of the pointer to be pressed - threshold: 5 // a minimal movement is ok, but keep it low - }, + value: function attachEdge(edge) { + if (this.edges.indexOf(edge) === -1) { + this.edges.push(edge); + } + } + }, { + key: 'detachEdge', - getTouchAction: function() { - return [TOUCH_ACTION_AUTO]; - }, + /** + * Detach a edge from the node + * @param {Edge} edge + */ + value: function detachEdge(edge) { + var index = this.edges.indexOf(edge); + if (index != -1) { + this.edges.splice(index, 1); + } + } + }, { + key: 'togglePhysics', - process: function(input) { - var options = this.options; - var validPointers = input.pointers.length === options.pointers; - var validMovement = input.distance < options.threshold; - var validTime = input.deltaTime > options.time; + /** + * Enable or disable the physics. + * @param status + */ + value: function togglePhysics(status) { + this.options.physics = status; + } + }, { + key: 'setOptions', - this._input = input; + /** + * Set or overwrite options for the node + * @param {Object} options an object with options + * @param {Object} constants and object with default, global options + */ + value: function setOptions(options) { + if (!options) { + return; + } - // we only allow little movement - // and we've reached an end event, so a tap is possible - if (!validMovement || !validPointers || (input.eventType & (INPUT_END | INPUT_CANCEL) && !validTime)) { - this.reset(); - } else if (input.eventType & INPUT_START) { - this.reset(); - this._timer = setTimeoutContext(function() { - this.state = STATE_RECOGNIZED; - this.tryEmit(); - }, options.time, this); - } else if (input.eventType & INPUT_END) { - return STATE_RECOGNIZED; - } - return STATE_FAILED; - }, + // basic options + if (options.id !== undefined) { + this.id = options.id; + } - reset: function() { - clearTimeout(this._timer); - }, + if (this.id === undefined) { + throw 'Node must have an id'; + } - emit: function(input) { - if (this.state !== STATE_RECOGNIZED) { - return; - } + if (options.x !== undefined) { + this.x = options.x;this.predefinedPosition = true; + } + if (options.y !== undefined) { + this.y = options.y;this.predefinedPosition = true; + } + if (options.value !== undefined) { + this.value = options.value; + } - if (input && (input.eventType & INPUT_END)) { - this.manager.emit(this.options.event + 'up', input); + // this transforms all shorthands into fully defined options + Node.parseOptions(this.options, options); + + // copy group options + if (typeof options.group === 'number' || typeof options.group === 'string' && options.group != '') { + var groupObj = this.grouplist.get(options.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); + } + + // load the images + if (this.options.image !== undefined && this.options.image != '') { + if (this.imagelist) { + this.imageObj = this.imagelist.load(this.options.image, this.options.brokenImage); } else { - this._input.timeStamp = now(); - this.manager.emit(this.options.event, this._input); + throw 'No imagelist provided'; } + } + + this.updateShape(); + this.updateLabelModule(); + + // reset the size of the node, this can be changed + this._reset(); + } + }, { + key: 'updateLabelModule', + value: function updateLabelModule() { + this.labelModule.setOptions(this.options); + } + }, { + key: 'updateShape', + value: function updateShape() { + // choose draw method depending on the shape + switch (this.options.shape) { + case 'box': + this.shape = new _Box2['default'](this.options, this.body, this.labelModule); + break; + case 'circle': + this.shape = new _Circle2['default'](this.options, this.body, this.labelModule); + break; + case 'circularImage': + this.shape = new _CircularImage2['default'](this.options, this.body, this.labelModule, this.imageObj); + break; + case 'database': + this.shape = new _Database2['default'](this.options, this.body, this.labelModule); + break; + case 'diamond': + this.shape = new _Diamond2['default'](this.options, this.body, this.labelModule); + break; + case 'dot': + this.shape = new _Dot2['default'](this.options, this.body, this.labelModule); + break; + case 'ellipse': + this.shape = new _Ellipse2['default'](this.options, this.body, this.labelModule); + break; + case 'icon': + this.shape = new _Icon2['default'](this.options, this.body, this.labelModule); + break; + case 'image': + this.shape = new _Image2['default'](this.options, this.body, this.labelModule, this.imageObj); + break; + case 'square': + this.shape = new _Square2['default'](this.options, this.body, this.labelModule); + break; + case 'star': + this.shape = new _Star2['default'](this.options, this.body, this.labelModule); + break; + case 'text': + this.shape = new _Text2['default'](this.options, this.body, this.labelModule); + break; + case 'triangle': + this.shape = new _Triangle2['default'](this.options, this.body, this.labelModule); + break; + case 'triangleDown': + this.shape = new _TriangleDown2['default'](this.options, this.body, this.labelModule); + break; + default: + this.shape = new _Ellipse2['default'](this.options, this.body, this.labelModule); + break; + } + this._reset(); } - }); - - /** - * Rotate - * Recognized when two or more pointer are moving in a circular motion. - * @constructor - * @extends AttrRecognizer - */ - function RotateRecognizer() { - AttrRecognizer.apply(this, arguments); - } + }, { + key: 'select', - inherit(RotateRecognizer, AttrRecognizer, { /** - * @namespace - * @memberof RotateRecognizer + * select this node */ - defaults: { - event: 'rotate', - threshold: 0, - pointers: 2 - }, - - getTouchAction: function() { - return [TOUCH_ACTION_NONE]; - }, - - attrTest: function(input) { - return this._super.attrTest.call(this, input) && - (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN); + value: function select() { + this.selected = true; + this._reset(); } - }); + }, { + key: 'unselect', - /** - * Swipe - * Recognized when the pointer is moving fast (velocity), with enough distance in the allowed direction. - * @constructor - * @extends AttrRecognizer - */ - function SwipeRecognizer() { - AttrRecognizer.apply(this, arguments); - } + /** + * unselect this node + */ + value: function unselect() { + this.selected = false; + this._reset(); + } + }, { + key: '_reset', - inherit(SwipeRecognizer, AttrRecognizer, { /** - * @namespace - * @memberof SwipeRecognizer + * Reset the calculated size of the node, forces it to recalculate its size + * @private */ - defaults: { - event: 'swipe', - threshold: 10, - velocity: 0.65, - direction: DIRECTION_HORIZONTAL | DIRECTION_VERTICAL, - pointers: 1 - }, + value: function _reset() { + this.shape.width = undefined; + this.shape.height = undefined; + } + }, { + key: 'getTitle', - getTouchAction: function() { - return PanRecognizer.prototype.getTouchAction.call(this); - }, + /** + * get the title of this node. + * @return {string} title The title of the node, or undefined when no title + * has been set. + */ + value: function getTitle() { + return typeof this.options.title === 'function' ? this.options.title() : this.options.title; + } + }, { + key: 'distanceToBorder', - attrTest: function(input) { - var direction = this.options.direction; - var velocity; + /** + * 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 + */ + value: function distanceToBorder(ctx, angle) { + return this.shape.distanceToBorder(ctx, angle); + } + }, { + key: 'isFixed', - if (direction & (DIRECTION_HORIZONTAL | DIRECTION_VERTICAL)) { - velocity = input.velocity; - } else if (direction & DIRECTION_HORIZONTAL) { - velocity = input.velocityX; - } else if (direction & DIRECTION_VERTICAL) { - velocity = input.velocityY; - } + /** + * Check if this node has a fixed x and y position + * @return {boolean} true if fixed, false if not + */ + value: function isFixed() { + return this.options.fixed.x && this.options.fixed.y; + } + }, { + key: 'isSelected', - return this._super.attrTest.call(this, input) && - direction & input.direction && - input.distance > this.options.threshold && - abs(velocity) > this.options.velocity && input.eventType & INPUT_END; - }, + /** + * check if this node is selecte + * @return {boolean} selected True if node is selected, else false + */ + value: function isSelected() { + return this.selected; + } + }, { + key: 'getValue', - emit: function(input) { - var direction = directionStr(input.direction); - if (direction) { - this.manager.emit(this.options.event + direction, input); - } + /** + * Retrieve the value of the node. Can be undefined + * @return {Number} value + */ + value: function getValue() { + return this.value; + } + }, { + key: 'setValueRange', - this.manager.emit(this.options.event, input); + /** + * Adjust the value range of the node. The node will adjust it's size + * based on its value. + * @param {Number} min + * @param {Number} max + */ + value: function setValueRange(min, max, total) { + if (this.value !== undefined) { + var scale = this.options.scaling.customScalingFunction(min, max, total, this.value); + var sizeDiff = this.options.scaling.max - this.options.scaling.min; + if (this.options.scaling.label.enabled === true) { + var fontDiff = this.options.scaling.label.max - this.options.scaling.label.min; + this.options.font.size = this.options.scaling.label.min + scale * fontDiff; + } + this.options.size = this.options.scaling.min + scale * sizeDiff; + } } - }); + }, { + key: 'draw', - /** - * A tap is ecognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur - * between the given interval and position. The delay option can be used to recognize multi-taps without firing - * a single tap. - * - * The eventData from the emitted event contains the property `tapCount`, which contains the amount of - * multi-taps being recognized. - * @constructor - * @extends Recognizer - */ - function TapRecognizer() { - Recognizer.apply(this, arguments); + /** + * Draw this node in the given canvas + * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); + * @param {CanvasRenderingContext2D} ctx + */ + value: function draw(ctx) { + this.shape.draw(ctx, this.x, this.y, this.selected, this.hover); + } + }, { + key: 'resize', - // previous time and center, - // used for tap counting - this.pTime = false; - this.pCenter = false; + /** + * 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 + */ + value: function resize(ctx) { + this.shape.resize(ctx); + } + }, { + key: 'isOverlappingWith', - this._timer = null; - this._input = null; - this.count = 0; - } + /** + * 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 + */ + value: function isOverlappingWith(obj) { + return this.shape.left < obj.right && this.shape.left + this.shape.width > obj.left && this.shape.top < obj.bottom && this.shape.top + this.shape.height > obj.top; + } + }], [{ + key: 'parseOptions', - inherit(TapRecognizer, Recognizer, { /** - * @namespace - * @memberof PinchRecognizer + * This process all possible shorthands in the new options and makes sure that the parentOptions are fully defined. + * Static so it can also be used by the handler. + * @param parentOptions + * @param newOptions */ - defaults: { - event: 'tap', - pointers: 1, - taps: 1, - interval: 300, // max time between the multi-tap taps - time: 250, // max time of the pointer to be down (like finger on the screen) - threshold: 2, // a minimal movement is ok, but keep it low - posThreshold: 10 // a multi-tap can be a bit off the initial position - }, + value: function parseOptions(parentOptions, newOptions) { + var fields = ['borderWidth', 'borderWidthSelected', 'brokenImage', 'customScalingFunction', 'font', 'hidden', 'icon', 'id', 'image', 'label', 'level', 'physics', 'shape', 'size', 'title', 'value', 'x', 'y']; + util.selectiveDeepExtend(fields, parentOptions, newOptions); + + // individual shape newOptions + if (newOptions.color !== undefined) { + var parsedColor = util.parseColor(newOptions.color); + util.fillIfDefined(parentOptions.color, parsedColor); + } - getTouchAction: function() { - return [TOUCH_ACTION_MANIPULATION]; - }, + if (newOptions.fixed !== undefined) { + if (typeof newOptions.fixed === 'boolean') { + parentOptions.fixed.x = true; + parentOptions.fixed.y = true; + } else { + if (newOptions.fixed.x !== undefined && typeof newOptions.fixed.x === 'boolean') { + parentOptions.fixed.x = newOptions.fixed.x; + } + if (newOptions.fixed.y !== undefined && typeof newOptions.fixed.y === 'boolean') { + parentOptions.fixed.y = newOptions.fixed.y; + } + } + } + } + }]); - process: function(input) { - var options = this.options; + return Node; + })(); - var validPointers = input.pointers.length === options.pointers; - var validMovement = input.distance < options.threshold; - var validTouchTime = input.deltaTime < options.time; + exports['default'] = Node; + module.exports = exports['default']; - this.reset(); +/***/ }, +/* 68 */ +/***/ function(module, exports, __webpack_require__) { - if ((input.eventType & INPUT_START) && (this.count === 0)) { - return this.failTimeout(); - } + 'use strict'; - // we only allow little movement - // and we've reached an end event, so a tap is possible - if (validMovement && validTouchTime && validPointers) { - if (input.eventType != INPUT_END) { - return this.failTimeout(); - } + var _slicedToArray = function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } else { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } }; - var validInterval = this.pTime ? (input.timeStamp - this.pTime < options.interval) : true; - var validMultiTap = !this.pCenter || getDistance(this.pCenter, input.center) < options.posThreshold; + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; - this.pTime = input.timeStamp; - this.pCenter = input.center; + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); - if (!validMultiTap || !validInterval) { - this.count = 1; - } else { - this.count += 1; - } + Object.defineProperty(exports, '__esModule', { + value: true + }); + var util = __webpack_require__(1); - this._input = input; + var Label = (function () { + function Label(body, options) { + _classCallCheck(this, Label); - // if tap count matches we have recognized it, - // else it has began recognizing... - var tapCount = this.count % options.taps; - if (tapCount === 0) { - // no failing requirements, immediately trigger the tap event - // or wait as long as the multitap interval to trigger - if (!this.hasRequireFailures()) { - return STATE_RECOGNIZED; - } else { - this._timer = setTimeoutContext(function() { - this.state = STATE_RECOGNIZED; - this.tryEmit(); - }, options.interval, this); - return STATE_BEGAN; - } - } - } - return STATE_FAILED; - }, + this.body = body; - failTimeout: function() { - this._timer = setTimeoutContext(function() { - this.state = STATE_FAILED; - }, this.options.interval, this); - return STATE_FAILED; - }, + this.fontOptions = {}; + this.defaultOptions = { + color: '#343434', + size: 14, // px + face: 'arial', + background: 'none', + stroke: 0, // px + strokeColor: 'white', + align: 'horizontal' + }; + util.extend(this.fontOptions, this.defaultOptions); - reset: function() { - clearTimeout(this._timer); - }, + this.setOptions(options); + this.size = { top: 0, left: 0, width: 0, height: 0, yLine: 0 }; // could be cached + } - emit: function() { - if (this.state == STATE_RECOGNIZED ) { - this._input.tapCount = this.count; - this.manager.emit(this.options.event, this._input); - } - } - }); + _createClass(Label, [{ + key: 'setOptions', + value: function setOptions(options) { + this.options = options; - /** - * Simple way to create an manager with a default set of recognizers. - * @param {HTMLElement} element - * @param {Object} [options] - * @constructor - */ - function Hammer(element, options) { - options = options || {}; - options.recognizers = ifUndefined(options.recognizers, Hammer.defaults.preset); - return new Manager(element, options); - } + if (options.label !== undefined) { + this.labelDirty = true; + } - /** - * @const {string} - */ - Hammer.VERSION = '2.0.4'; + Label.parseOptions(this.fontOptions, options); + } + }, { + key: 'draw', - /** - * default settings - * @namespace - */ - Hammer.defaults = { /** - * set if DOM events are being triggered. - * But this is slower and unused by simple implementations, so disabled by default. - * @type {Boolean} - * @default false + * Main function. This is called from anything that wants to draw a label. + * @param ctx + * @param x + * @param y + * @param selected + * @param baseline */ - domEvents: false, + value: function draw(ctx, x, y, selected) { + var baseline = arguments[4] === undefined ? 'middle' : arguments[4]; + + // if no label, return + if (this.options.label === undefined) { + return; + } // check if we have to render the label + var viewFontSize = this.fontOptions.size * this.body.view.scale; + if (this.options.label && viewFontSize < this.options.scaling.label.drawThreshold - 1) { + return; + } // update the size cache if required + this.calculateLabelSize(ctx, selected, x, y, baseline); + + // create the fontfill background + this._drawBackground(ctx); + // draw text + this._drawText(ctx, selected, x, y, baseline); + } + }, { + key: '_drawBackground', /** - * The value for the touchAction property/fallback. - * When set to `compute` it will magically set the correct value based on the added recognizers. - * @type {String} - * @default compute + * Draws the label background + * @param {CanvasRenderingContext2D} ctx + * @private */ - touchAction: TOUCH_ACTION_COMPUTE, + value: function _drawBackground(ctx) { + if (this.fontOptions.background !== undefined && this.fontOptions.background !== 'none') { + ctx.fillStyle = this.fontOptions.background; + + var lineMargin = 2; + + switch (this.fontOptions.align) { + case 'middle': + ctx.fillRect(-this.size.width * 0.5, -this.size.height * 0.5, this.size.width, this.size.height); + break; + case 'top': + ctx.fillRect(-this.size.width * 0.5, -(this.size.height + lineMargin), this.size.width, this.size.height); + break; + case 'bottom': + ctx.fillRect(-this.size.width * 0.5, lineMargin, this.size.width, this.size.height); + break; + default: + ctx.fillRect(this.size.left, this.size.top, this.size.width, this.size.height); + break; + } + } + } + }, { + key: '_drawText', /** - * @type {Boolean} - * @default true + * + * @param ctx + * @param x + * @param baseline + * @private */ - enable: true, + value: function _drawText(ctx, selected, x, y) { + var baseline = arguments[4] === undefined ? 'middle' : arguments[4]; + + var fontSize = this.fontOptions.size; + var viewFontSize = fontSize * this.body.view.scale; + // 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 (viewFontSize >= this.options.scaling.label.maxVisible) { + fontSize = Number(this.options.scaling.label.maxVisible) / this.body.view.scale; + } + + var yLine = this.size.yLine; + + var _getColor = this._getColor(viewFontSize); + + var _getColor2 = _slicedToArray(_getColor, 2); + + var fontColor = _getColor2[0]; + var strokeColor = _getColor2[1]; + + var _setAlignment = this._setAlignment(ctx, x, yLine, baseline); + + var _setAlignment2 = _slicedToArray(_setAlignment, 2); + + x = _setAlignment2[0]; + yLine = _setAlignment2[1]; + + // configure context for drawing the text + ctx.font = (selected ? 'bold ' : '') + fontSize + 'px ' + this.fontOptions.face; + ctx.fillStyle = fontColor; + ctx.textAlign = 'center'; + + // set the strokeWidth + if (this.fontOptions.stroke > 0) { + ctx.lineWidth = this.fontOptions.stroke; + ctx.strokeStyle = strokeColor; + ctx.lineJoin = 'round'; + } + + // draw the text + for (var i = 0; i < this.lineCount; i++) { + if (this.fontOptions.stroke > 0) { + ctx.strokeText(this.lines[i], x, yLine); + } + ctx.fillText(this.lines[i], x, yLine); + yLine += fontSize; + } + } + }, { + key: '_setAlignment', + value: function _setAlignment(ctx, x, yLine, baseline) { + // check for label alignment (for edges) + // TODO: make alignment for nodes + if (this.fontOptions.align !== 'horizontal') { + x = 0; + yLine = 0; + + var lineMargin = 2; + if (this.fontOptions.align === 'top') { + ctx.textBaseline = 'alphabetic'; + yLine -= 2 * lineMargin; // distance from edge, required because we use alphabetic. Alphabetic has less difference between browsers + } else if (this.fontOptions.align === 'bottom') { + ctx.textBaseline = 'hanging'; + yLine += 2 * lineMargin; // distance from edge, required because we use hanging. Hanging has less difference between browsers + } else { + ctx.textBaseline = 'middle'; + } + } else { + ctx.textBaseline = baseline; + } + + return [x, yLine]; + } + }, { + key: '_getColor', /** - * EXPERIMENTAL FEATURE -- can be removed/changed - * Change the parent input target element. - * If Null, then it is being set the to main element. - * @type {Null|EventTarget} - * @default null + * fade in when relative scale is between threshold and threshold - 1. + * If the relative scale would be smaller than threshold -1 the draw function would have returned before coming here. + * + * @param viewFontSize + * @returns {*[]} + * @private */ - inputTarget: null, + value: function _getColor(viewFontSize) { + var fontColor = this.fontOptions.color || '#000000'; + var strokeColor = this.fontOptions.strokeColor || '#ffffff'; + if (viewFontSize <= this.options.scaling.label.drawThreshold) { + var opacity = Math.max(0, Math.min(1, 1 - (this.options.scaling.label.drawThreshold - viewFontSize))); + fontColor = util.overrideOpacity(fontColor, opacity); + strokeColor = util.overrideOpacity(strokeColor, opacity); + } + return [fontColor, strokeColor]; + } + }, { + key: 'getTextSize', /** - * force an input class - * @type {Null|Function} - * @default null + * + * @param ctx + * @param selected + * @returns {{width: number, height: number}} */ - inputClass: null, + value: function getTextSize(ctx) { + var selected = arguments[1] === undefined ? false : arguments[1]; + + var size = { + width: this._processLabel(ctx, selected), + height: this.fontOptions.size * this.lineCount, + lineCount: this.lineCount + }; + return size; + } + }, { + key: 'calculateLabelSize', /** - * Default recognizer setup when calling `Hammer()` - * When creating a new Manager these will be skipped. - * @type {Array} + * + * @param ctx + * @param selected + * @param x + * @param y + * @param baseline */ - preset: [ - // RecognizerClass, options, [recognizeWith, ...], [requireFailure, ...] - [RotateRecognizer, { enable: false }], - [PinchRecognizer, { enable: false }, ['rotate']], - [SwipeRecognizer,{ direction: DIRECTION_HORIZONTAL }], - [PanRecognizer, { direction: DIRECTION_HORIZONTAL }, ['swipe']], - [TapRecognizer], - [TapRecognizer, { event: 'doubletap', taps: 2 }, ['tap']], - [PressRecognizer] - ], + value: function calculateLabelSize(ctx, selected) { + var x = arguments[2] === undefined ? 0 : arguments[2]; + var y = arguments[3] === undefined ? 0 : arguments[3]; + var baseline = arguments[4] === undefined ? 'middle' : arguments[4]; + + if (this.labelDirty === true) { + this.size.width = this._processLabel(ctx, selected); + } + this.size.height = this.fontOptions.size * this.lineCount; + this.size.left = x - this.size.width * 0.5; + this.size.top = y - this.size.height * 0.5; + this.size.yLine = y + (1 - this.lineCount) * 0.5 * this.fontOptions.size; + if (baseline === 'hanging') { + this.size.top += 0.5 * this.fontOptions.size; + this.size.top += 4; // distance from node, required because we use hanging. Hanging has less difference between browsers + this.size.yLine += 4; // distance from node + } + + this.labelDirty = false; + } + }, { + key: '_processLabel', /** - * Some CSS properties can be used to improve the working of Hammer. - * Add them to this method and they will be set when creating a new Manager. - * @namespace + * This calculates the width as well as explodes the label string and calculates the amount of lines. + * @param ctx + * @param selected + * @returns {number} + * @private */ - cssProps: { - /** - * Disables text selection to improve the dragging gesture. Mainly for desktop browsers. - * @type {String} - * @default 'none' - */ - userSelect: 'none', + value: function _processLabel(ctx, selected) { + var width = 0; + var lines = ['']; + var lineCount = 0; + if (this.options.label !== undefined) { + lines = String(this.options.label).split('\n'); + lineCount = lines.length; + ctx.font = (selected ? 'bold ' : '') + this.fontOptions.size + 'px ' + this.fontOptions.face; + width = ctx.measureText(lines[0]).width; + for (var i = 1; i < lineCount; i++) { + var lineWidth = ctx.measureText(lines[i]).width; + width = lineWidth > width ? lineWidth : width; + } + } + this.lines = lines; + this.lineCount = lineCount; + + return width; + } + }], [{ + key: 'parseOptions', + value: function parseOptions(parentOptions, newOptions) { + if (newOptions.font !== undefined) { + if (typeof newOptions.font === 'string') { + var newOptionsArray = newOptions.font.split(' '); + parentOptions.size = newOptionsArray[0].replace('px', ''); + parentOptions.face = newOptionsArray[1]; + parentOptions.color = newOptionsArray[2]; + } else if (typeof newOptions.font === 'object') { + util.fillIfDefined(parentOptions, newOptions.font); + } + parentOptions.size = Number(parentOptions.size); + } + } + }]); - /** - * Disable the Windows Phone grippers when pressing an element. - * @type {String} - * @default 'none' - */ - touchSelect: 'none', + return Label; + })(); - /** - * 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. - * @type {String} - * @default 'none' - */ - touchCallout: 'none', + exports['default'] = Label; + module.exports = exports['default']; - /** - * Specifies whether zooming is enabled. Used by IE10> - * @type {String} - * @default 'none' - */ - contentZooming: 'none', +/***/ }, +/* 69 */ +/***/ function(module, exports, __webpack_require__) { - /** - * Specifies that an entire element should be draggable instead of its contents. Mainly for desktop browsers. - * @type {String} - * @default 'none' - */ - userDrag: 'none', + 'use strict'; - /** - * Overrides the highlight color shown when the user taps a link or a JavaScript - * clickable element in iOS. This property obeys the alpha value, if specified. - * @type {String} - * @default 'rgba(0,0,0,0)' - */ - tapHighlightColor: 'rgba(0,0,0,0)' - } - }; + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; - var STOP = 1; - var FORCED_STOP = 2; + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; - /** - * Manager - * @param {HTMLElement} element - * @param {Object} [options] - * @constructor - */ - function Manager(element, options) { - options = options || {}; + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); - this.options = merge(options, Hammer.defaults); - this.options.inputTarget = this.options.inputTarget || element; + Object.defineProperty(exports, '__esModule', { + value: true + }); - this.handlers = {}; - this.session = {}; - this.recognizers = []; + var _Label = __webpack_require__(68); - this.element = element; - this.input = createInputInstance(this); - this.touchAction = new TouchAction(this, this.options.touchAction); + var _Label2 = _interopRequireWildcard(_Label); - toggleCssProps(this, true); + var _BezierEdgeDynamic = __webpack_require__(85); - each(options.recognizers, function(item) { - var recognizer = this.add(new (item[0])(item[1])); - item[2] && recognizer.recognizeWith(item[2]); - item[3] && recognizer.requireFailure(item[3]); - }, this); - } + var _BezierEdgeDynamic2 = _interopRequireWildcard(_BezierEdgeDynamic); - Manager.prototype = { - /** - * set options - * @param {Object} options - * @returns {Manager} - */ - set: function(options) { - extend(this.options, options); + var _BezierEdgeStatic = __webpack_require__(86); - // Options that need a little more setup - if (options.touchAction) { - this.touchAction.update(); - } - if (options.inputTarget) { - // Clean up existing event listeners and reinitialize - this.input.destroy(); - this.input.target = options.inputTarget; - this.input.init(); - } - return this; - }, + var _BezierEdgeStatic2 = _interopRequireWildcard(_BezierEdgeStatic); - /** - * stop recognizing for this session. - * This session will be discarded, when a new [input]start event is fired. - * When forced, the recognizer cycle is stopped immediately. - * @param {Boolean} [force] - */ - stop: function(force) { - this.session.stopped = force ? FORCED_STOP : STOP; - }, + var _StraightEdge = __webpack_require__(87); - /** - * run the recognizers! - * called by the inputHandler function on every movement of the pointers (touches) - * it walks through all the recognizers and tries to detect the gesture that is being made - * @param {Object} inputData - */ - recognize: function(inputData) { - var session = this.session; - if (session.stopped) { - return; - } + var _StraightEdge2 = _interopRequireWildcard(_StraightEdge); - // run the touch-action polyfill - this.touchAction.preventDefaults(inputData); + var util = __webpack_require__(1); - var recognizer; - var recognizers = this.recognizers; + /** + * @class Edge + * + * A edge connects two nodes + * @param {Object} properties Object with options. Must contain + * At least options from and to. + * Available options: 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 + */ + + var Edge = (function () { + function Edge(options, body, globalOptions) { + _classCallCheck(this, Edge); + + if (body === undefined) { + throw 'No body provided'; + } + this.options = util.bridgeObject(globalOptions); + this.body = body; - // this holds the recognizer that is being recognized. - // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED - // if no recognizer is detecting a thing, it is set to `null` - var curRecognizer = session.curRecognizer; + // initialize variables + this.id = undefined; + this.fromId = undefined; + this.toId = undefined; + this.value = undefined; + this.selected = false; + this.hover = false; + this.labelDirty = true; + this.colorDirty = true; - // reset when the last recognizer is recognized - // or when we're in a new session - if (!curRecognizer || (curRecognizer && curRecognizer.state & STATE_RECOGNIZED)) { - curRecognizer = session.curRecognizer = null; - } + this.from = undefined; // a node + this.to = undefined; // a node - var i = 0; - while (i < recognizers.length) { - recognizer = recognizers[i]; + this.edgeType = undefined; - // find out if we are allowed try to recognize the input for this one. - // 1. allow if the session is NOT forced stopped (see the .stop() method) - // 2. allow if we still haven't recognized a gesture in this session, or the this recognizer is the one - // that is being recognized. - // 3. allow if the recognizer is allowed to run simultaneous with the current recognized recognizer. - // this can be setup with the `recognizeWith()` method on the recognizer. - if (session.stopped !== FORCED_STOP && ( // 1 - !curRecognizer || recognizer == curRecognizer || // 2 - recognizer.canRecognizeWith(curRecognizer))) { // 3 - recognizer.recognize(inputData); - } else { - recognizer.reset(); - } + this.connected = false; - // if the recognizer has been recognizing the input as a valid gesture, we want to store this one as the - // current active recognizer. but only if we don't already have an active recognizer - if (!curRecognizer && recognizer.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED)) { - curRecognizer = session.curRecognizer = recognizer; - } - i++; - } - }, + this.labelModule = new _Label2['default'](this.body, this.options); + + this.setOptions(options); + } + + _createClass(Edge, [{ + key: 'setOptions', /** - * get a recognizer by its event name. - * @param {Recognizer|String} recognizer - * @returns {Recognizer|Null} + * Set or overwrite options for the edge + * @param {Object} options an object with options + * @param doNotEmit */ - get: function(recognizer) { - if (recognizer instanceof Recognizer) { - return recognizer; + value: function setOptions(options) { + if (!options) { + return; + } + this.colorDirty = true; + + Edge.parseOptions(this.options, options); + + if (options.id !== undefined) { + this.id = options.id; + } + if (options.from !== undefined) { + this.fromId = options.from; + } + if (options.to !== undefined) { + this.toId = options.to; + } + if (options.title !== undefined) { + this.title = options.title; + } + if (options.value !== undefined) { + this.value = options.value; + } + + // A node is connected when it has a from and to node that both exist in the network.body.nodes. + this.connect(); + + // update label Module + this.updateLabelModule(); + + var dataChanged = this.updateEdgeType(); + return dataChanged; + } + }, { + key: 'updateLabelModule', + value: function updateLabelModule() { + this.labelModule.setOptions(this.options); + } + }, { + key: 'updateEdgeType', + value: function updateEdgeType() { + var dataChanged = false; + var changeInType = true; + if (this.edgeType !== undefined) { + if (this.edgeType instanceof _BezierEdgeDynamic2['default'] && this.options.smooth.enabled === true && this.options.smooth.dynamic === true) { + changeInType = false; + } + if (this.edgeType instanceof _BezierEdgeStatic2['default'] && this.options.smooth.enabled === true && this.options.smooth.dynamic === false) { + changeInType = false; + } + if (this.edgeType instanceof _StraightEdge2['default'] && this.options.smooth.enabled === false) { + changeInType = false; } - var recognizers = this.recognizers; - for (var i = 0; i < recognizers.length; i++) { - if (recognizers[i].options.event == recognizer) { - return recognizers[i]; - } + if (changeInType === true) { + dataChanged = this.edgeType.cleanup(); } - return null; - }, + } + + if (changeInType === true) { + if (this.options.smooth.enabled === true) { + if (this.options.smooth.dynamic === true) { + dataChanged = true; + this.edgeType = new _BezierEdgeDynamic2['default'](this.options, this.body, this.labelModule); + } else { + this.edgeType = new _BezierEdgeStatic2['default'](this.options, this.body, this.labelModule); + } + } else { + this.edgeType = new _StraightEdge2['default'](this.options, this.body, this.labelModule); + } + } else { + // if nothing changes, we just set the options. + this.edgeType.setOptions(this.options); + } + + return dataChanged; + } + }, { + key: 'togglePhysics', /** - * add a recognizer to the manager - * existing recognizers with the same event name will be removed - * @param {Recognizer} recognizer - * @returns {Recognizer|Manager} + * Enable or disable the physics. + * @param status */ - add: function(recognizer) { - if (invokeArrayArg(recognizer, 'add', this)) { - return this; + value: function togglePhysics(status) { + if (this.options.smooth.enabled === true && this.options.smooth.dynamic === true) { + if (this.via === undefined) { + this.via.pptions.physics = status; } + } + this.options.physics = status; + } + }, { + key: 'connect', - // remove existing - var existing = this.get(recognizer.options.event); - if (existing) { - this.remove(existing); - } + /** + * Connect an edge to its nodes + */ + value: function connect() { + this.disconnect(); - this.recognizers.push(recognizer); - recognizer.manager = this; + this.from = this.body.nodes[this.fromId] || undefined; + this.to = this.body.nodes[this.toId] || undefined; + this.connected = this.from !== undefined && this.to !== undefined; - this.touchAction.update(); - return recognizer; - }, + 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); + } + } + } + }, { + key: 'disconnect', /** - * remove a recognizer by name or instance - * @param {Recognizer|String} recognizer - * @returns {Manager} + * Disconnect an edge from its nodes */ - remove: function(recognizer) { - if (invokeArrayArg(recognizer, 'remove', this)) { - return this; - } + value: function disconnect() { + if (this.from) { + this.from.detachEdge(this); + this.from = undefined; + } + if (this.to) { + this.to.detachEdge(this); + this.to = undefined; + } - var recognizers = this.recognizers; - recognizer = this.get(recognizer); - recognizers.splice(inArray(recognizers, recognizer), 1); + this.connected = false; + } + }, { + key: 'getTitle', - this.touchAction.update(); - return this; - }, + /** + * get the title of this edge. + * @return {string} title The title of the edge, or undefined when no title + * has been set. + */ + value: function getTitle() { + return typeof this.title === 'function' ? this.title() : this.title; + } + }, { + key: 'isSelected', /** - * bind event - * @param {String} events - * @param {Function} handler - * @returns {EventEmitter} this + * check if this node is selecte + * @return {boolean} selected True if node is selected, else false */ - on: function(events, handler) { - var handlers = this.handlers; - each(splitStr(events), function(event) { - handlers[event] = handlers[event] || []; - handlers[event].push(handler); - }); - return this; - }, + value: function isSelected() { + return this.selected; + } + }, { + key: 'getValue', /** - * unbind event, leave emit blank to remove all handlers - * @param {String} events - * @param {Function} [handler] - * @returns {EventEmitter} this + * Retrieve the value of the edge. Can be undefined + * @return {Number} value */ - off: function(events, handler) { - var handlers = this.handlers; - each(splitStr(events), function(event) { - if (!handler) { - delete handlers[event]; - } else { - handlers[event].splice(inArray(handlers[event], handler), 1); - } - }); - return this; - }, + value: function getValue() { + return this.value; + } + }, { + key: 'setValueRange', /** - * emit event to the listeners - * @param {String} event - * @param {Object} data + * Adjust the value range of the edge. The edge will adjust it's width + * based on its value. + * @param {Number} min + * @param {Number} max + * @param total */ - emit: function(event, data) { - // we also want to trigger dom events - if (this.options.domEvents) { - triggerDomEvent(event, data); - } + value: function setValueRange(min, max, total) { + if (this.value !== undefined) { + var scale = this.options.scaling.customScalingFunction(min, max, total, this.value); + var widthDiff = this.options.scaling.max - this.options.scaling.min; + if (this.options.scaling.label.enabled === true) { + var fontDiff = this.options.scaling.label.max - this.options.scaling.label.min; + this.options.font.size = this.options.scaling.label.min + scale * fontDiff; + } + this.options.width = this.options.scaling.min + scale * widthDiff; + } + } + }, { + key: 'draw', - // no handlers, so skip it all - var handlers = this.handlers[event] && this.handlers[event].slice(); - if (!handlers || !handlers.length) { - return; - } + /** + * 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 + */ + value: function draw(ctx) { + var via = this.edgeType.drawLine(ctx, this.selected, this.hover); + this.drawArrows(ctx, via); + this.drawLabel(ctx, via); + } + }, { + key: 'drawArrows', + value: function drawArrows(ctx, viaNode) { + if (this.options.arrows.from.enabled === true) { + this.edgeType.drawArrowHead(ctx, 'from', viaNode, this.selected, this.hover); + } + if (this.options.arrows.middle.enabled === true) { + this.edgeType.drawArrowHead(ctx, 'middle', viaNode, this.selected, this.hover); + } + if (this.options.arrows.to.enabled === true) { + this.edgeType.drawArrowHead(ctx, 'to', viaNode, this.selected, this.hover); + } + } + }, { + key: 'drawLabel', + value: function drawLabel(ctx, viaNode) { + if (this.options.label !== undefined) { + // set style + var node1 = this.from; + var node2 = this.to; + var selected = this.from.selected || this.to.selected || this.selected; + if (node1.id != node2.id) { + var point = this.edgeType.getPoint(0.5, viaNode); + ctx.save(); + + // if the label has to be rotated: + if (this.options.font.align !== 'horizontal') { + this.labelModule.calculateLabelSize(ctx, selected, point.x, point.y); + ctx.translate(point.x, this.labelModule.size.yLine); + this._rotateForLabelAlignment(ctx); + } - data.type = event; - data.preventDefault = function() { - data.srcEvent.preventDefault(); - }; + // draw the label + this.labelModule.draw(ctx, point.x, point.y, selected); + ctx.restore(); + } else { + var x, y; + var radius = this.options.selfReferenceSize; + if (node1.width > node1.height) { + x = node1.x + node1.width * 0.5; + y = node1.y - radius; + } else { + x = node1.x + radius; + y = node1.y - node1.height * 0.5; + } + point = this._pointOnCircle(x, y, radius, 0.125); - var i = 0; - while (i < handlers.length) { - handlers[i](data); - i++; + this.labelModule.draw(ctx, point.x, point.y, selected); } - }, + } + } + }, { + key: 'isOverlappingWith', /** - * destroy the manager and unbinds all events - * it doesn't unbind dom events, that is the user own responsibility + * 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 */ - destroy: function() { - this.element && toggleCssProps(this, false); - - this.handlers = {}; - this.session = {}; - this.input.destroy(); - this.element = null; + value: function isOverlappingWith(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.edgeType.getDistanceToEdge(xFrom, yFrom, xTo, yTo, xObj, yObj); + + return dist < distMax; + } else { + return false; + } } - }; - - /** - * add/remove the css properties as defined in manager.options.cssProps - * @param {Manager} manager - * @param {Boolean} add - */ - function toggleCssProps(manager, add) { - var element = manager.element; - each(manager.options.cssProps, function(value, name) { - element.style[prefixed(element.style, name)] = add ? value : ''; - }); - } - - /** - * trigger dom event - * @param {String} event - * @param {Object} data - */ - function triggerDomEvent(event, data) { - var gestureEvent = document.createEvent('Event'); - gestureEvent.initEvent(event, true, true); - gestureEvent.gesture = data; - data.target.dispatchEvent(gestureEvent); - } - - extend(Hammer, { - INPUT_START: INPUT_START, - INPUT_MOVE: INPUT_MOVE, - INPUT_END: INPUT_END, - INPUT_CANCEL: INPUT_CANCEL, - - STATE_POSSIBLE: STATE_POSSIBLE, - STATE_BEGAN: STATE_BEGAN, - STATE_CHANGED: STATE_CHANGED, - STATE_ENDED: STATE_ENDED, - STATE_RECOGNIZED: STATE_RECOGNIZED, - STATE_CANCELLED: STATE_CANCELLED, - STATE_FAILED: STATE_FAILED, - - DIRECTION_NONE: DIRECTION_NONE, - DIRECTION_LEFT: DIRECTION_LEFT, - DIRECTION_RIGHT: DIRECTION_RIGHT, - DIRECTION_UP: DIRECTION_UP, - DIRECTION_DOWN: DIRECTION_DOWN, - DIRECTION_HORIZONTAL: DIRECTION_HORIZONTAL, - DIRECTION_VERTICAL: DIRECTION_VERTICAL, - DIRECTION_ALL: DIRECTION_ALL, - - Manager: Manager, - Input: Input, - TouchAction: TouchAction, - - TouchInput: TouchInput, - MouseInput: MouseInput, - PointerEventInput: PointerEventInput, - TouchMouseInput: TouchMouseInput, - SingleTouchInput: SingleTouchInput, + }, { + key: '_rotateForLabelAlignment', - Recognizer: Recognizer, - AttrRecognizer: AttrRecognizer, - Tap: TapRecognizer, - Pan: PanRecognizer, - Swipe: SwipeRecognizer, - Pinch: PinchRecognizer, - Rotate: RotateRecognizer, - Press: PressRecognizer, + /** + * Rotates the canvas so the text is most readable + * @param {CanvasRenderingContext2D} ctx + * @private + */ + value: function _rotateForLabelAlignment(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; + } - on: addEventListeners, - off: removeEventListeners, - each: each, - merge: merge, - extend: extend, - inherit: inherit, - bindFn: bindFn, - prefixed: prefixed - }); + ctx.rotate(angleInDegrees); + } + }, { + key: '_pointOnCircle', - if ("function" == TYPE_FUNCTION && __webpack_require__(71)) { - !(__WEBPACK_AMD_DEFINE_RESULT__ = function() { - return Hammer; - }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); - } else if (typeof module != 'undefined' && module.exports) { - module.exports = Hammer; - } else { - window[exportName] = Hammer; - } + /** + * 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 + */ + value: function _pointOnCircle(x, y, radius, percentage) { + var angle = percentage * 2 * Math.PI; + return { + x: x + radius * Math.cos(angle), + y: y - radius * Math.sin(angle) + }; + } + }, { + key: 'select', + value: function select() { + this.selected = true; + } + }, { + key: 'unselect', + value: function unselect() { + this.selected = false; + } + }], [{ + key: 'parseOptions', + value: function parseOptions(parentOptions, newOptions) { + var fields = ['id', 'font', 'from', 'hidden', 'hoverWidth', 'label', 'length', 'line', 'opacity', 'physics', 'selfReferenceSize', 'to', 'title', 'value', 'width', 'widthMin', 'widthMax', 'widthSelectionMultiplier']; - })(window, document, 'Hammer'); + // only deep extend the items in the field array. These do not have shorthand. + util.selectiveDeepExtend(fields, parentOptions, newOptions); + util.mergeOptions(parentOptions, newOptions, 'smooth'); + util.mergeOptions(parentOptions, newOptions, 'dashes'); -/***/ }, -/* 71 */ -/***/ function(module, exports, __webpack_require__) { + // set the scaling newOptions + if (newOptions.scaling !== undefined) { + if (newOptions.scaling.min !== undefined) { + parentOptions.scaling.min = newOptions.scaling.min; + } + if (newOptions.scaling.max !== undefined) { + parentOptions.scaling.max = newOptions.scaling.max; + } + util.mergeOptions(parentOptions.scaling, newOptions.scaling, 'label'); + } - /* WEBPACK VAR INJECTION */(function(__webpack_amd_options__) {module.exports = __webpack_amd_options__; + // hanlde multiple input cases for arrows + if (newOptions.arrows !== undefined) { + if (typeof newOptions.arrows === 'string') { + var arrows = newOptions.arrows.toLowerCase(); + if (arrows.indexOf('to') != -1) { + parentOptions.arrows.to.enabled = true; + } + if (arrows.indexOf('middle') != -1) { + parentOptions.arrows.middle.enabled = true; + } + if (arrows.indexOf('from') != -1) { + parentOptions.arrows.from.enabled = true; + } + } else if (typeof newOptions.arrows === 'object') { + util.mergeOptions(parentOptions.arrows, newOptions.arrows, 'to'); + util.mergeOptions(parentOptions.arrows, newOptions.arrows, 'middle'); + util.mergeOptions(parentOptions.arrows, newOptions.arrows, 'from'); + } else { + throw new Error('The arrow newOptions can only be an object or a string. Refer to the documentation. You used:' + JSON.stringify(newOptions.arrows)); + } + } - /* WEBPACK VAR INJECTION */}.call(exports, {})) + // hanlde multiple input cases for color + if (newOptions.color !== undefined) { + if (util.isString(newOptions.color)) { + parentOptions.color.color = newOptions.color; + parentOptions.color.highlight = newOptions.color; + parentOptions.color.hover = newOptions.color; + parentOptions.color.inherit.enabled = false; + } else { + var colorsDefined = false; + if (newOptions.color.color !== undefined) { + parentOptions.color.color = newOptions.color.color;colorsDefined = true; + } + if (newOptions.color.highlight !== undefined) { + parentOptions.color.highlight = newOptions.color.highlight;colorsDefined = true; + } + if (newOptions.color.hover !== undefined) { + parentOptions.color.hover = newOptions.color.hover;colorsDefined = true; + } + if (newOptions.color.opacity !== undefined) { + parentOptions.color.opacity = newOptions.color.opacity; + } + + if (newOptions.color.inherit === undefined && colorsDefined === true) { + parentOptions.color.inherit.enabled = false; + } + } + util.mergeOptions(parentOptions.color, newOptions.color, 'inherit'); + } + } + }]); + + return Edge; + })(); + + exports['default'] = Edge; + module.exports = exports['default']; /***/ }, -/* 72 */ +/* 70 */ /***/ function(module, exports, __webpack_require__) { "use strict"; - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + Object.defineProperty(exports, "__esModule", { + value: true + }); + var BarnesHutSolver = (function () { function BarnesHutSolver(body, physicsBody, options) { _classCallCheck(this, BarnesHutSolver); @@ -31204,502 +32751,470 @@ return /******/ (function(modules) { // webpackBootstrap this.setOptions(options); } - _prototypeProperties(BarnesHutSolver, null, { - setOptions: { - value: function setOptions(options) { - this.options = options; - this.thetaInversed = 1 / this.options.theta; - }, - writable: true, - configurable: true - }, - solve: { + _createClass(BarnesHutSolver, [{ + key: "setOptions", + value: function setOptions(options) { + this.options = options; + this.thetaInversed = 1 / this.options.theta; + } + }, { + key: "solve", + + /** + * This function calculates the forces the nodes apply on eachother based on a gravitational model. + * The Barnes Hut method is used to speed up this N-body simulation. + * + * @private + */ + value: function solve() { + if (this.options.gravitationalConstant != 0) { + var node; + var nodes = this.body.nodes; + var nodeIndices = this.physicsBody.physicsNodeIndices; + var nodeCount = nodeIndices.length; + // create the tree + var barnesHutTree = this._formBarnesHutTree(nodes, nodeIndices); - /** - * This function calculates the forces the nodes apply on eachother based on a gravitational model. - * The Barnes Hut method is used to speed up this N-body simulation. - * - * @private - */ - value: function solve() { - if (this.options.gravitationalConstant != 0) { - var node; - var nodes = this.body.nodes; - var nodeIndices = this.physicsBody.physicsNodeIndices; - var nodeCount = nodeIndices.length; - - // create the tree - var barnesHutTree = this._formBarnesHutTree(nodes, nodeIndices); - - // for debugging - this.barnesHutTree = 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 BarnesHutSolver 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); - } + // for debugging + this.barnesHutTree = 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 BarnesHutSolver 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); } } - }, - writable: true, - configurable: true - }, - _getForceContribution: { - + } + } + }, { + key: "_getForceContribution", - /** - * 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 parentBranch - * @param node - * @private - */ - value: function _getForceContribution(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); + /** + * 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 parentBranch + * @param node + * @private + */ + value: function _getForceContribution(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); - // BarnesHutSolver condition - // original condition : s/d < theta = passed === d/s > 1/theta = passed - // calcSize = 1/s --> d * 1/s > 1/theta = passed - if (distance * parentBranch.calcSize > this.thetaInversed) { - // duplicate code to reduce function calls to speed up program - if (distance === 0) { - distance = 0.1 * Math.random(); - dx = distance; - } - var gravityForce = this.options.gravitationalConstant * parentBranch.mass * node.options.mass / (distance * distance * distance); - var fx = dx * gravityForce; - var fy = dy * gravityForce; + // BarnesHutSolver condition + // original condition : s/d < theta = passed === d/s > 1/theta = passed + // calcSize = 1/s --> d * 1/s > 1/theta = passed + if (distance * parentBranch.calcSize > this.thetaInversed) { + // duplicate code to reduce function calls to speed up program + if (distance === 0) { + distance = 0.1 * Math.random(); + dx = distance; + } + var gravityForce = this.options.gravitationalConstant * parentBranch.mass * node.options.mass / (distance * distance * distance); + var fx = dx * gravityForce; + var fy = dy * gravityForce; - this.physicsBody.forces[node.id].x += fx; - this.physicsBody.forces[node.id].y += fy; + this.physicsBody.forces[node.id].x += fx; + this.physicsBody.forces[node.id].y += 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 { - // 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.options.gravitationalConstant * parentBranch.mass * node.options.mass / (distance * distance * distance); - var fx = dx * gravityForce; - var fy = dy * gravityForce; - - this.physicsBody.forces[node.id].x += fx; - this.physicsBody.forces[node.id].y += fy; + // 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.options.gravitationalConstant * parentBranch.mass * node.options.mass / (distance * distance * distance); + var fx = dx * gravityForce; + var fy = dy * gravityForce; + + this.physicsBody.forces[node.id].x += fx; + this.physicsBody.forces[node.id].y += fy; } } } - }, - writable: true, - configurable: true - }, - _formBarnesHutTree: { - - - /** - * This function constructs the barnesHut tree recursively. It creates the root, splits it and starts placing the nodes. - * - * @param nodes - * @param nodeIndices - * @private - */ - value: function _formBarnesHutTree(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; + } + } + }, { + key: "_formBarnesHutTree", - // 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; - } + /** + * This function constructs the barnesHut tree recursively. It creates the root, splits it and starts placing the nodes. + * + * @param nodes + * @param nodeIndices + * @private + */ + value: function _formBarnesHutTree(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; } - } - // 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 = 0.00001; - 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 + if (x > maxX) { + maxX = x; } - }; - 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); + if (y < minY) { + minY = y; } + if (y > maxY) { + maxY = y; + } + } + } + // make the range a square + var sizeDiff = Math.abs(maxX - minX) - Math.abs(maxY - minY); // difference between X and Y + if (sizeDiff > 0) { + minY -= 0.5 * sizeDiff; + maxY += 0.5 * sizeDiff; + } // xSize > ySize + else { + minX += 0.5 * sizeDiff; + maxX -= 0.5 * sizeDiff; + } // xSize < ySize + + var minimumTreeSize = 0.00001; + 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); - // make global - return barnesHutTree; - }, - writable: true, - configurable: true - }, - _updateBranchMass: { + // 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); + } + } + // make global + return barnesHutTree; + } + }, { + key: "_updateBranchMass", - /** - * this updates the mass of a branch. this is increased by adding a node. - * - * @param parentBranch - * @param node - * @private - */ - value: function _updateBranchMass(parentBranch, node) { - var totalMass = parentBranch.mass + node.options.mass; - var totalMassInv = 1 / totalMass; + /** + * this updates the mass of a branch. this is increased by adding a node. + * + * @param parentBranch + * @param node + * @private + */ + value: function _updateBranchMass(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.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.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; - }, - writable: true, - configurable: true - }, - _placeInTree: { + parentBranch.mass = totalMass; + var biggestSize = Math.max(Math.max(node.height, node.radius), node.width); + parentBranch.maxWidth = parentBranch.maxWidth < biggestSize ? biggestSize : parentBranch.maxWidth; + } + }, { + key: "_placeInTree", + /** + * determine in which branch the node will be placed. + * + * @param parentBranch + * @param node + * @param skipMassUpdate + * @private + */ + value: function _placeInTree(parentBranch, node, skipMassUpdate) { + if (skipMassUpdate != true || skipMassUpdate === undefined) { + // update the mass of the branch. + this._updateBranchMass(parentBranch, node); + } - /** - * determine in which branch the node will be placed. - * - * @param parentBranch - * @param node - * @param skipMassUpdate - * @private - */ - value: function _placeInTree(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"); + } else { + // in SW + this._placeInRegion(parentBranch, node, "SW"); } - - 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 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"); - } + // in SE + this._placeInRegion(parentBranch, node, "SE"); } - }, - writable: true, - configurable: true - }, - _placeInRegion: { - + } + } + }, { + key: "_placeInRegion", - /** - * actually place the node in a region (or branch) - * - * @param parentBranch - * @param node - * @param region - * @private - */ - value: function _placeInRegion(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 + /** + * actually place the node in a region (or branch) + * + * @param parentBranch + * @param node + * @param region + * @private + */ + value: function _placeInRegion(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; - } - }, - writable: true, - configurable: true - }, - _splitBranch: { - - - /** - * this function splits a branch into 4 sub branches. If the branch contained a node, we place it in the subbranch - * after the split is complete. - * - * @param parentBranch - * @private - */ - value: function _splitBranch(parentBranch) { - // if the branch is shaded with a node, replace the node in the new subset. - var containedNode = null; - if (parentBranch.childrenCount === 1) { - containedNode = parentBranch.children.data; - parentBranch.mass = 0; - parentBranch.centerOfMass.x = 0; - parentBranch.centerOfMass.y = 0; - } - parentBranch.childrenCount = 4; - parentBranch.children.data = null; - this._insertRegion(parentBranch, "NW"); - this._insertRegion(parentBranch, "NE"); - this._insertRegion(parentBranch, "SW"); - this._insertRegion(parentBranch, "SE"); - - if (containedNode != null) { - this._placeInTree(parentBranch, containedNode); - } - }, - writable: true, - configurable: true - }, - _insertRegion: { + } + break; + case 4: + // place in branch + this._placeInTree(parentBranch.children[region], node); + break; + } + } + }, { + key: "_splitBranch", + /** + * this function splits a branch into 4 sub branches. If the branch contained a node, we place it in the subbranch + * after the split is complete. + * + * @param parentBranch + * @private + */ + value: function _splitBranch(parentBranch) { + // if the branch is shaded with a node, replace the node in the new subset. + var containedNode = null; + if (parentBranch.childrenCount === 1) { + containedNode = parentBranch.children.data; + parentBranch.mass = 0; + parentBranch.centerOfMass.x = 0; + parentBranch.centerOfMass.y = 0; + } + parentBranch.childrenCount = 4; + parentBranch.children.data = null; + this._insertRegion(parentBranch, "NW"); + this._insertRegion(parentBranch, "NE"); + this._insertRegion(parentBranch, "SW"); + this._insertRegion(parentBranch, "SE"); + + if (containedNode != null) { + this._placeInTree(parentBranch, containedNode); + } + } + }, { + key: "_insertRegion", - /** - * This function subdivides the region into four new segments. - * Specifically, this inserts a single new segment. - * It fills the children section of the parentBranch - * - * @param parentBranch - * @param region - * @param parentRange - * @private - */ - value: function _insertRegion(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; - } + /** + * This function subdivides the region into four new segments. + * Specifically, this inserts a single new segment. + * It fills the children section of the parentBranch + * + * @param parentBranch + * @param region + * @param parentRange + * @private + */ + value: function _insertRegion(parentBranch, region) { + var minX, maxX, minY, maxY; + var childSize = 0.5 * parentBranch.size; + switch (region) { + case "NW": + minX = parentBranch.range.minX; + maxX = parentBranch.range.minX + childSize; + minY = parentBranch.range.minY; + maxY = parentBranch.range.minY + childSize; + break; + case "NE": + minX = parentBranch.range.minX + childSize; + maxX = parentBranch.range.maxX; + minY = parentBranch.range.minY; + maxY = parentBranch.range.minY + childSize; + break; + case "SW": + minX = parentBranch.range.minX; + maxX = parentBranch.range.minX + childSize; + minY = parentBranch.range.minY + childSize; + maxY = parentBranch.range.maxY; + break; + case "SE": + minX = parentBranch.range.minX + childSize; + maxX = parentBranch.range.maxX; + minY = parentBranch.range.minY + childSize; + maxY = parentBranch.range.maxY; + break; + } + parentBranch.children[region] = { + centerOfMass: { x: 0, y: 0 }, + mass: 0, + range: { minX: minX, maxX: maxX, minY: minY, maxY: maxY }, + size: 0.5 * parentBranch.size, + calcSize: 2 * parentBranch.calcSize, + children: { data: null }, + maxWidth: 0, + level: parentBranch.level + 1, + childrenCount: 0 + }; + } + }, { + key: "_debug", - 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 - }; - }, - writable: true, - configurable: true - }, - _debug: { + //--------------------------- DEBUGGING BELOW ---------------------------// + /** + * This function is for debugging purposed, it draws the tree. + * + * @param ctx + * @param color + * @private + */ + value: function _debug(ctx, color) { + if (this.barnesHutTree !== undefined) { + ctx.lineWidth = 1; + this._drawBranch(this.barnesHutTree.root, ctx, color); + } + } + }, { + key: "_drawBranch", - //--------------------------- DEBUGGING BELOW ---------------------------// + /** + * This function is for debugging purposes. It draws the branches recursively. + * + * @param branch + * @param ctx + * @param color + * @private + */ + value: function _drawBranch(branch, ctx, color) { + if (color === undefined) { + color = "#FF0000"; + } + if (branch.childrenCount === 4) { + this._drawBranch(branch.children.NW, ctx); + this._drawBranch(branch.children.NE, ctx); + this._drawBranch(branch.children.SE, ctx); + this._drawBranch(branch.children.SW, ctx); + } + ctx.strokeStyle = color; + ctx.beginPath(); + ctx.moveTo(branch.range.minX, branch.range.minY); + ctx.lineTo(branch.range.maxX, branch.range.minY); + ctx.stroke(); - /** - * This function is for debugging purposed, it draws the tree. - * - * @param ctx - * @param color - * @private - */ - value: function _debug(ctx, color) { - if (this.barnesHutTree !== undefined) { - ctx.lineWidth = 1; + ctx.beginPath(); + ctx.moveTo(branch.range.maxX, branch.range.minY); + ctx.lineTo(branch.range.maxX, branch.range.maxY); + ctx.stroke(); - this._drawBranch(this.barnesHutTree.root, ctx, color); - } - }, - writable: true, - configurable: true - }, - _drawBranch: { + 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(); - /** - * This function is for debugging purposes. It draws the branches recursively. - * - * @param branch - * @param ctx - * @param color - * @private + /* + if (branch.mass > 0) { + ctx.circle(branch.centerOfMass.x, branch.centerOfMass.y, 3*branch.mass); + ctx.stroke(); + } */ - value: function _drawBranch(branch, ctx, color) { - if (color === undefined) { - color = "#FF0000"; - } - - if (branch.childrenCount === 4) { - this._drawBranch(branch.children.NW, ctx); - this._drawBranch(branch.children.NE, ctx); - this._drawBranch(branch.children.SE, ctx); - this._drawBranch(branch.children.SW, ctx); - } - ctx.strokeStyle = color; - ctx.beginPath(); - ctx.moveTo(branch.range.minX, branch.range.minY); - ctx.lineTo(branch.range.maxX, branch.range.minY); - ctx.stroke(); - - ctx.beginPath(); - ctx.moveTo(branch.range.maxX, branch.range.minY); - ctx.lineTo(branch.range.maxX, branch.range.maxY); - ctx.stroke(); - - ctx.beginPath(); - ctx.moveTo(branch.range.maxX, branch.range.maxY); - ctx.lineTo(branch.range.minX, branch.range.maxY); - ctx.stroke(); - - ctx.beginPath(); - ctx.moveTo(branch.range.minX, branch.range.maxY); - ctx.lineTo(branch.range.minX, branch.range.minY); - ctx.stroke(); - - /* - if (branch.mass > 0) { - ctx.circle(branch.centerOfMass.x, branch.centerOfMass.y, 3*branch.mass); - ctx.stroke(); - } - */ - }, - writable: true, - configurable: true } - }); + }]); return BarnesHutSolver; })(); - module.exports = BarnesHutSolver; + exports["default"] = BarnesHutSolver; + module.exports = exports["default"]; /***/ }, -/* 73 */ +/* 71 */ /***/ function(module, exports, __webpack_require__) { "use strict"; - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + Object.defineProperty(exports, "__esModule", { + value: true + }); + var RepulsionSolver = (function () { function RepulsionSolver(body, physicsBody, options) { _classCallCheck(this, RepulsionSolver); @@ -31709,91 +33224,92 @@ return /******/ (function(modules) { // webpackBootstrap this.setOptions(options); } - _prototypeProperties(RepulsionSolver, null, { - setOptions: { - value: function setOptions(options) { - this.options = options; - }, - writable: true, - configurable: true - }, - solve: { - /** - * Calculate the forces the nodes apply on each other based on a repulsion field. - * This field is linearly approximated. - * - * @private - */ - value: function solve() { - var dx, dy, distance, fx, fy, repulsingForce, node1, node2; + _createClass(RepulsionSolver, [{ + key: "setOptions", + value: function setOptions(options) { + this.options = options; + } + }, { + key: "solve", - var nodes = this.body.nodes; - var nodeIndices = this.physicsBody.physicsNodeIndices; - var forces = this.physicsBody.forces; + /** + * Calculate the forces the nodes apply on each other based on a repulsion field. + * This field is linearly approximated. + * + * @private + */ + value: function solve() { + var dx, dy, distance, fx, fy, repulsingForce, node1, node2; - // repulsing forces between nodes - var nodeDistance = this.options.nodeDistance; + var nodes = this.body.nodes; + var nodeIndices = this.physicsBody.physicsNodeIndices; + var forces = this.physicsBody.forces; - // approximation constants - var a = -2 / 3 / nodeDistance; - var b = 4 / 3; + // repulsing forces between nodes + var nodeDistance = this.options.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 (var i = 0; i < nodeIndices.length - 1; i++) { - node1 = nodes[nodeIndices[i]]; - for (var j = i + 1; j < nodeIndices.length; j++) { - node2 = nodes[nodeIndices[j]]; + // approximation constants + var a = -2 / 3 / nodeDistance; + var b = 4 / 3; - dx = node2.x - node1.x; - dy = node2.y - node1.y; - distance = Math.sqrt(dx * dx + dy * dy); + // 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 (var i = 0; i < nodeIndices.length - 1; i++) { + node1 = nodes[nodeIndices[i]]; + for (var j = i + 1; j < nodeIndices.length; j++) { + node2 = nodes[nodeIndices[j]]; + + dx = node2.x - node1.x; + dy = node2.y - node1.y; + distance = Math.sqrt(dx * dx + dy * dy); + + // same condition as BarnesHutSolver, making sure nodes are never 100% overlapping. + if (distance === 0) { + distance = 0.1 * Math.random(); + dx = distance; + } - // same condition as BarnesHutSolver, making sure nodes are never 100% overlapping. - if (distance === 0) { - distance = 0.1 * Math.random(); - dx = distance; + if (distance < 2 * nodeDistance) { + if (distance < 0.5 * nodeDistance) { + repulsingForce = 1; + } else { + repulsingForce = a * distance + b; // linear approx of 1 / (1 + Math.exp((distance / nodeDistance - 1) * steepness)) } + repulsingForce = repulsingForce / distance; - if (distance < 2 * nodeDistance) { - if (distance < 0.5 * nodeDistance) { - repulsingForce = 1; - } else { - repulsingForce = a * distance + b; // linear approx of 1 / (1 + Math.exp((distance / nodeDistance - 1) * steepness)) - } - repulsingForce = repulsingForce / distance; - - fx = dx * repulsingForce; - fy = dy * repulsingForce; + fx = dx * repulsingForce; + fy = dy * repulsingForce; - forces[node1.id].x -= fx; - forces[node1.id].y -= fy; - forces[node2.id].x += fx; - forces[node2.id].y += fy; - } + forces[node1.id].x -= fx; + forces[node1.id].y -= fy; + forces[node2.id].x += fx; + forces[node2.id].y += fy; } } - }, - writable: true, - configurable: true + } } - }); + }]); return RepulsionSolver; })(); - module.exports = RepulsionSolver; + exports["default"] = RepulsionSolver; + module.exports = exports["default"]; /***/ }, -/* 74 */ +/* 72 */ /***/ function(module, exports, __webpack_require__) { "use strict"; - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + Object.defineProperty(exports, "__esModule", { + value: true + }); + var HierarchicalRepulsionSolver = (function () { function HierarchicalRepulsionSolver(body, physicsBody, options) { _classCallCheck(this, HierarchicalRepulsionSolver); @@ -31803,88 +33319,88 @@ return /******/ (function(modules) { // webpackBootstrap this.setOptions(options); } - _prototypeProperties(HierarchicalRepulsionSolver, null, { - setOptions: { - value: function setOptions(options) { - this.options = options; - }, - writable: true, - configurable: true - }, - solve: { + _createClass(HierarchicalRepulsionSolver, [{ + key: "setOptions", + value: function setOptions(options) { + this.options = options; + } + }, { + key: "solve", - /** - * Calculate the forces the nodes apply on each other based on a repulsion field. - * This field is linearly approximated. - * - * @private - */ - value: function solve() { - var dx, dy, distance, fx, fy, repulsingForce, node1, node2, i, j; + /** + * Calculate the forces the nodes apply on each other based on a repulsion field. + * This field is linearly approximated. + * + * @private + */ + value: function solve() { + var dx, dy, distance, fx, fy, repulsingForce, node1, node2, i, j; - var nodes = this.body.nodes; - var nodeIndices = this.physicsBody.physicsNodeIndices; - var forces = this.physicsBody.forces; - - // repulsing forces between nodes - var nodeDistance = this.options.nodeDistance; - - // we loop from i over all but the last entree in the array - // j loops from i+1 to the last. This way we do not double count any of the indices, nor i === j - for (i = 0; i < nodeIndices.length - 1; i++) { - node1 = nodes[nodeIndices[i]]; - for (j = i + 1; j < nodeIndices.length; j++) { - node2 = nodes[nodeIndices[j]]; - - // nodes only affect nodes on their level - if (node1.level === node2.level) { - dx = node2.x - node1.x; - dy = node2.y - node1.y; - distance = Math.sqrt(dx * dx + dy * dy); - - var steepness = 0.05; - if (distance < nodeDistance) { - repulsingForce = -Math.pow(steepness * distance, 2) + Math.pow(steepness * nodeDistance, 2); - } else { - repulsingForce = 0; - } - // normalize force with - if (distance === 0) { - distance = 0.01; - } else { - repulsingForce = repulsingForce / distance; - } - fx = dx * repulsingForce; - fy = dy * repulsingForce; + var nodes = this.body.nodes; + var nodeIndices = this.physicsBody.physicsNodeIndices; + var forces = this.physicsBody.forces; + + // repulsing forces between nodes + var nodeDistance = this.options.nodeDistance; - forces[node1.id].x -= fx; - forces[node1.id].y -= fy; - forces[node2.id].x += fx; - forces[node2.id].y += fy; + // we loop from i over all but the last entree in the array + // j loops from i+1 to the last. This way we do not double count any of the indices, nor i === j + for (i = 0; i < nodeIndices.length - 1; i++) { + node1 = nodes[nodeIndices[i]]; + for (j = i + 1; j < nodeIndices.length; j++) { + node2 = nodes[nodeIndices[j]]; + + // nodes only affect nodes on their level + if (node1.level === node2.level) { + dx = node2.x - node1.x; + dy = node2.y - node1.y; + distance = Math.sqrt(dx * dx + dy * dy); + + var steepness = 0.05; + if (distance < nodeDistance) { + repulsingForce = -Math.pow(steepness * distance, 2) + Math.pow(steepness * nodeDistance, 2); + } else { + repulsingForce = 0; + } + // normalize force with + if (distance === 0) { + distance = 0.01; + } else { + repulsingForce = repulsingForce / distance; } + fx = dx * repulsingForce; + fy = dy * repulsingForce; + + forces[node1.id].x -= fx; + forces[node1.id].y -= fy; + forces[node2.id].x += fx; + forces[node2.id].y += fy; } } - }, - writable: true, - configurable: true + } } - }); + }]); return HierarchicalRepulsionSolver; })(); - module.exports = HierarchicalRepulsionSolver; + exports["default"] = HierarchicalRepulsionSolver; + module.exports = exports["default"]; /***/ }, -/* 75 */ +/* 73 */ /***/ function(module, exports, __webpack_require__) { "use strict"; - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + Object.defineProperty(exports, "__esModule", { + value: true + }); + var SpringSolver = (function () { function SpringSolver(body, physicsBody, options) { _classCallCheck(this, SpringSolver); @@ -31894,110 +33410,106 @@ return /******/ (function(modules) { // webpackBootstrap this.setOptions(options); } - _prototypeProperties(SpringSolver, null, { - setOptions: { - value: function setOptions(options) { - this.options = options; - }, - writable: true, - configurable: true - }, - solve: { - - /** - * This function calculates the springforces on the nodes, accounting for the support nodes. - * - * @private - */ - value: function solve() { - var edgeLength, edge; - var edgeIndices = this.physicsBody.physicsEdgeIndices; - var edges = this.body.edges; + _createClass(SpringSolver, [{ + key: "setOptions", + value: function setOptions(options) { + this.options = options; + } + }, { + key: "solve", - // forces caused by the edges, modelled as springs - for (var i = 0; i < edgeIndices.length; i++) { - edge = edges[edgeIndices[i]]; - if (edge.connected === true) { - // only calculate forces if nodes are in the same sector - if (this.body.nodes[edge.toId] !== undefined && this.body.nodes[edge.fromId] !== undefined) { - if (edge.edgeType.via !== undefined) { - edgeLength = edge.options.length === undefined ? this.options.springLength : edge.options.length; - var node1 = edge.to; - var node2 = edge.edgeType.via; - var node3 = edge.from; - - - this._calculateSpringForce(node1, node2, 0.5 * edgeLength); - this._calculateSpringForce(node2, node3, 0.5 * edgeLength); - } else { - // the * 1.5 is here so the edge looks as large as a smooth edge. It does not initially because the smooth edges use - // the support nodes which exert a repulsive force on the to and from nodes, making the edge appear larger. - edgeLength = edge.options.length === undefined ? this.options.springLength * 1.5 : edge.options.length; - this._calculateSpringForce(edge.from, edge.to, edgeLength); - } + /** + * This function calculates the springforces on the nodes, accounting for the support nodes. + * + * @private + */ + value: function solve() { + var edgeLength, edge; + var edgeIndices = this.physicsBody.physicsEdgeIndices; + var edges = this.body.edges; + + // forces caused by the edges, modelled as springs + for (var i = 0; i < edgeIndices.length; i++) { + edge = edges[edgeIndices[i]]; + if (edge.connected === true) { + // only calculate forces if nodes are in the same sector + if (this.body.nodes[edge.toId] !== undefined && this.body.nodes[edge.fromId] !== undefined) { + if (edge.edgeType.via !== undefined) { + edgeLength = edge.options.length === undefined ? this.options.springLength : edge.options.length; + var node1 = edge.to; + var node2 = edge.edgeType.via; + var node3 = edge.from; + + this._calculateSpringForce(node1, node2, 0.5 * edgeLength); + this._calculateSpringForce(node2, node3, 0.5 * edgeLength); + } else { + // the * 1.5 is here so the edge looks as large as a smooth edge. It does not initially because the smooth edges use + // the support nodes which exert a repulsive force on the to and from nodes, making the edge appear larger. + edgeLength = edge.options.length === undefined ? this.options.springLength * 1.5 : edge.options.length; + this._calculateSpringForce(edge.from, edge.to, edgeLength); } } } - }, - writable: true, - configurable: true - }, - _calculateSpringForce: { - + } + } + }, { + key: "_calculateSpringForce", - /** - * This is the code actually performing the calculation for the function above. - * - * @param node1 - * @param node2 - * @param edgeLength - * @private - */ - value: function _calculateSpringForce(node1, node2, edgeLength) { - var dx, dy, fx, fy, springForce, distance; + /** + * This is the code actually performing the calculation for the function above. + * + * @param node1 + * @param node2 + * @param edgeLength + * @private + */ + value: function _calculateSpringForce(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); - distance = distance === 0 ? 0.01 : distance; + dx = node1.x - node2.x; + dy = node1.y - node2.y; + distance = Math.sqrt(dx * dx + dy * dy); + distance = distance === 0 ? 0.01 : distance; - // the 1/distance is so the fx and fy can be calculated without sine or cosine. - springForce = this.options.springConstant * (edgeLength - distance) / distance; + // the 1/distance is so the fx and fy can be calculated without sine or cosine. + springForce = this.options.springConstant * (edgeLength - distance) / distance; - fx = dx * springForce; - fy = dy * springForce; + fx = dx * springForce; + fy = dy * springForce; - // handle the case where one node is not part of the physcis - if (this.physicsBody.forces[node1.id] !== undefined) { - this.physicsBody.forces[node1.id].x += fx; - this.physicsBody.forces[node1.id].y += fy; - } + // handle the case where one node is not part of the physcis + if (this.physicsBody.forces[node1.id] !== undefined) { + this.physicsBody.forces[node1.id].x += fx; + this.physicsBody.forces[node1.id].y += fy; + } - if (this.physicsBody.forces[node2.id] !== undefined) { - this.physicsBody.forces[node2.id].x -= fx; - this.physicsBody.forces[node2.id].y -= fy; - } - }, - writable: true, - configurable: true + if (this.physicsBody.forces[node2.id] !== undefined) { + this.physicsBody.forces[node2.id].x -= fx; + this.physicsBody.forces[node2.id].y -= fy; + } } - }); + }]); return SpringSolver; })(); - module.exports = SpringSolver; + exports["default"] = SpringSolver; + module.exports = exports["default"]; /***/ }, -/* 76 */ +/* 74 */ /***/ function(module, exports, __webpack_require__) { "use strict"; - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + Object.defineProperty(exports, "__esModule", { + value: true + }); + var HierarchicalSpringSolver = (function () { function HierarchicalSpringSolver(body, physicsBody, options) { _classCallCheck(this, HierarchicalSpringSolver); @@ -32007,119 +33519,118 @@ return /******/ (function(modules) { // webpackBootstrap this.setOptions(options); } - _prototypeProperties(HierarchicalSpringSolver, null, { - setOptions: { - value: function setOptions(options) { - this.options = options; - }, - writable: true, - configurable: true - }, - solve: { - - /** - * This function calculates the springforces on the nodes, accounting for the support nodes. - * - * @private - */ - value: function solve() { - var edgeLength, edge; - var dx, dy, fx, fy, springForce, distance; - var edges = this.body.edges; - var factor = 0.5; - - var edgeIndices = this.physicsBody.physicsEdgeIndices; - var nodeIndices = this.physicsBody.physicsNodeIndices; - var forces = this.physicsBody.forces; - - // initialize the spring force counters - for (var i = 0; i < nodeIndices.length; i++) { - var nodeId = nodeIndices[i]; - forces[nodeId].springFx = 0; - forces[nodeId].springFy = 0; - } + _createClass(HierarchicalSpringSolver, [{ + key: "setOptions", + value: function setOptions(options) { + this.options = options; + } + }, { + key: "solve", + /** + * This function calculates the springforces on the nodes, accounting for the support nodes. + * + * @private + */ + value: function solve() { + var edgeLength, edge; + var dx, dy, fx, fy, springForce, distance; + var edges = this.body.edges; + var factor = 0.5; + + var edgeIndices = this.physicsBody.physicsEdgeIndices; + var nodeIndices = this.physicsBody.physicsNodeIndices; + var forces = this.physicsBody.forces; + + // initialize the spring force counters + for (var i = 0; i < nodeIndices.length; i++) { + var nodeId = nodeIndices[i]; + forces[nodeId].springFx = 0; + forces[nodeId].springFy = 0; + } - // forces caused by the edges, modelled as springs - for (var i = 0; i < edgeIndices.length; i++) { - edge = edges[edgeIndices[i]]; - if (edge.connected === true) { - edgeLength = edge.options.length === undefined ? this.options.springLength : edge.options.length; + // forces caused by the edges, modelled as springs + for (var i = 0; i < edgeIndices.length; i++) { + edge = edges[edgeIndices[i]]; + if (edge.connected === true) { + edgeLength = edge.options.length === undefined ? this.options.springLength : edge.options.length; - dx = edge.from.x - edge.to.x; - dy = edge.from.y - edge.to.y; - distance = Math.sqrt(dx * dx + dy * dy); - distance = distance === 0 ? 0.01 : distance; + dx = edge.from.x - edge.to.x; + dy = edge.from.y - edge.to.y; + distance = Math.sqrt(dx * dx + dy * dy); + distance = distance === 0 ? 0.01 : distance; - // the 1/distance is so the fx and fy can be calculated without sine or cosine. - springForce = this.options.springConstant * (edgeLength - distance) / distance; + // the 1/distance is so the fx and fy can be calculated without sine or cosine. + springForce = this.options.springConstant * (edgeLength - distance) / distance; - fx = dx * springForce; - fy = dy * springForce; + fx = dx * springForce; + fy = dy * springForce; - if (edge.to.level != edge.from.level) { - forces[edge.toId].springFx -= fx; - forces[edge.toId].springFy -= fy; - forces[edge.fromId].springFx += fx; - forces[edge.fromId].springFy += fy; - } else { - forces[edge.toId].x -= factor * fx; - forces[edge.toId].y -= factor * fy; - forces[edge.fromId].x += factor * fx; - forces[edge.fromId].y += factor * fy; - } + if (edge.to.level != edge.from.level) { + forces[edge.toId].springFx -= fx; + forces[edge.toId].springFy -= fy; + forces[edge.fromId].springFx += fx; + forces[edge.fromId].springFy += fy; + } else { + forces[edge.toId].x -= factor * fx; + forces[edge.toId].y -= factor * fy; + forces[edge.fromId].x += factor * fx; + forces[edge.fromId].y += factor * fy; } } + } - // normalize spring forces - var springForce = 1; - var springFx, springFy; - for (var i = 0; i < nodeIndices.length; i++) { - var nodeId = nodeIndices[i]; - springFx = Math.min(springForce, Math.max(-springForce, forces[nodeId].springFx)); - springFy = Math.min(springForce, Math.max(-springForce, forces[nodeId].springFy)); + // normalize spring forces + var springForce = 1; + var springFx, springFy; + for (var i = 0; i < nodeIndices.length; i++) { + var nodeId = nodeIndices[i]; + springFx = Math.min(springForce, Math.max(-springForce, forces[nodeId].springFx)); + springFy = Math.min(springForce, Math.max(-springForce, forces[nodeId].springFy)); - forces[nodeId].x += springFx; - forces[nodeId].y += springFy; - } + forces[nodeId].x += springFx; + forces[nodeId].y += springFy; + } - // retain energy balance - var totalFx = 0; - var totalFy = 0; - for (var i = 0; i < nodeIndices.length; i++) { - var nodeId = nodeIndices[i]; - totalFx += forces[nodeId].x; - totalFy += forces[nodeId].y; - } - var correctionFx = totalFx / nodeIndices.length; - var correctionFy = totalFy / nodeIndices.length; + // retain energy balance + var totalFx = 0; + var totalFy = 0; + for (var i = 0; i < nodeIndices.length; i++) { + var nodeId = nodeIndices[i]; + totalFx += forces[nodeId].x; + totalFy += forces[nodeId].y; + } + var correctionFx = totalFx / nodeIndices.length; + var correctionFy = totalFy / nodeIndices.length; - for (var i = 0; i < nodeIndices.length; i++) { - var nodeId = nodeIndices[i]; - forces[nodeId].x -= correctionFx; - forces[nodeId].y -= correctionFy; - } - }, - writable: true, - configurable: true + for (var i = 0; i < nodeIndices.length; i++) { + var nodeId = nodeIndices[i]; + forces[nodeId].x -= correctionFx; + forces[nodeId].y -= correctionFy; + } } - }); + }]); return HierarchicalSpringSolver; })(); - module.exports = HierarchicalSpringSolver; + exports["default"] = HierarchicalSpringSolver; + module.exports = exports["default"]; /***/ }, -/* 77 */ +/* 75 */ /***/ function(module, exports, __webpack_require__) { "use strict"; - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + Object.defineProperty(exports, "__esModule", { + value: true + }); + var CentralGravitySolver = (function () { function CentralGravitySolver(body, physicsBody, options) { _classCallCheck(this, CentralGravitySolver); @@ -32129,65 +33640,109 @@ return /******/ (function(modules) { // webpackBootstrap this.setOptions(options); } - _prototypeProperties(CentralGravitySolver, null, { - setOptions: { - value: function setOptions(options) { - this.options = options; - }, - writable: true, - configurable: true - }, - solve: { - value: function solve() { - var dx, dy, distance, node, i; - var nodes = this.body.nodes; - var nodeIndices = this.physicsBody.physicsNodeIndices; - var forces = this.physicsBody.forces; - + _createClass(CentralGravitySolver, [{ + key: "setOptions", + value: function setOptions(options) { + this.options = options; + } + }, { + key: "solve", + value: function solve() { + var dx, dy, distance, node, i; + var nodes = this.body.nodes; + var nodeIndices = this.physicsBody.physicsNodeIndices; + var forces = this.physicsBody.forces; - var gravity = this.options.centralGravity; - var gravityForce = 0; + var gravity = this.options.centralGravity; + var gravityForce = 0; - for (i = 0; i < nodeIndices.length; i++) { - var nodeId = nodeIndices[i]; - node = nodes[nodeId]; - dx = -node.x; - dy = -node.y; - distance = Math.sqrt(dx * dx + dy * dy); + for (i = 0; i < nodeIndices.length; i++) { + var nodeId = nodeIndices[i]; + node = nodes[nodeId]; + dx = -node.x; + dy = -node.y; + distance = Math.sqrt(dx * dx + dy * dy); - gravityForce = distance === 0 ? 0 : gravity / distance; - forces[nodeId].x = dx * gravityForce; - forces[nodeId].y = dy * gravityForce; - } - }, - writable: true, - configurable: true + gravityForce = distance === 0 ? 0 : gravity / distance; + forces[nodeId].x = dx * gravityForce; + forces[nodeId].y = dy * gravityForce; + } } - }); + }]); return CentralGravitySolver; })(); - module.exports = CentralGravitySolver; + exports["default"] = CentralGravitySolver; + module.exports = exports["default"]; /***/ }, -/* 78 */ +/* 76 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; + + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + + var _inherits = function (subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + + Object.defineProperty(exports, '__esModule', { + value: true + }); + + var _Node2 = __webpack_require__(67); + + var _Node3 = _interopRequireWildcard(_Node2); + + /** + * + */ + + var Cluster = (function (_Node) { + function Cluster(options, body, imagelist, grouplist, globalOptions) { + _classCallCheck(this, Cluster); + _get(Object.getPrototypeOf(Cluster.prototype), 'constructor', this).call(this, options, body, imagelist, grouplist, globalOptions); + + this.isCluster = true; + this.containedNodes = {}; + this.containedEdges = {}; + } + + _inherits(Cluster, _Node); + + return Cluster; + })(_Node3['default']); + + exports['default'] = Cluster; + module.exports = exports['default']; + +/***/ }, +/* 77 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; + + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + Object.defineProperty(exports, '__esModule', { + value: true + }); var util = __webpack_require__(1); var Hammer = __webpack_require__(41); - var hammerUtil = __webpack_require__(64); - var keycharm = __webpack_require__(65); + var hammerUtil = __webpack_require__(44); + var keycharm = __webpack_require__(81); var NavigationHandler = (function () { function NavigationHandler(body, canvas) { var _this = this; + _classCallCheck(this, NavigationHandler); this.body = body; @@ -32199,15 +33754,14 @@ return /******/ (function(modules) { // webpackBootstrap this.touchTime = 0; this.activated = false; - - this.body.emitter.on("release", this._stopMovement.bind(this)); - this.body.emitter.on("activate", function () { + this.body.emitter.on('release', this._stopMovement.bind(this)); + this.body.emitter.on('activate', function () { _this.activated = true;_this.configureKeyboardBindings(); }); - this.body.emitter.on("deactivate", function () { + this.body.emitter.on('deactivate', function () { _this.activated = false;_this.configureKeyboardBindings(); }); - this.body.emitter.on("destroy", function () { + this.body.emitter.on('destroy', function () { if (_this.keycharm !== undefined) { _this.keycharm.destroy(); } @@ -32216,263 +33770,236 @@ return /******/ (function(modules) { // webpackBootstrap this.options = {}; } - _prototypeProperties(NavigationHandler, null, { - setOptions: { - value: function setOptions(options) { - if (options !== undefined) { - this.options = options; - this.create(); - } - }, - writable: true, - configurable: true - }, - create: { - value: function create() { - if (this.options.showNavigationIcons === true) { - if (this.iconsCreated === false) { - this.loadNavigationElements(); - } - } else if (this.iconsCreated === true) { - this.cleanNavigation(); + _createClass(NavigationHandler, [{ + key: 'setOptions', + value: function setOptions(options) { + if (options !== undefined) { + this.options = options; + this.create(); + } + } + }, { + key: 'create', + value: function create() { + if (this.options.showNavigationIcons === true) { + if (this.iconsCreated === false) { + this.loadNavigationElements(); } + } else if (this.iconsCreated === true) { + this.cleanNavigation(); + } - this.configureKeyboardBindings(); - }, - writable: true, - configurable: true - }, - cleanNavigation: { - value: function cleanNavigation() { - // clean hammer bindings - if (this.navigationHammers.length != 0) { - for (var i = 0; i < this.navigationHammers.length; i++) { - this.navigationHammers[i].destroy(); - } - this.navigationHammers = []; + this.configureKeyboardBindings(); + } + }, { + key: 'cleanNavigation', + value: function cleanNavigation() { + // clean hammer bindings + if (this.navigationHammers.length != 0) { + for (var i = 0; i < this.navigationHammers.length; i++) { + this.navigationHammers[i].destroy(); } + this.navigationHammers = []; + } - this._navigationReleaseOverload = function () {}; - - // clean up previous navigation items - if (this.navigationDOM && this.navigationDOM.wrapper && this.navigationDOM.wrapper.parentNode) { - this.navigationDOM.wrapper.parentNode.removeChild(this.navigationDOM.wrapper); - } + this._navigationReleaseOverload = function () {}; - this.iconsCreated = false; - }, - writable: true, - configurable: true - }, - loadNavigationElements: { + // clean up previous navigation items + if (this.navigationDOM && this.navigationDOM.wrapper && this.navigationDOM.wrapper.parentNode) { + this.navigationDOM.wrapper.parentNode.removeChild(this.navigationDOM.wrapper); + } - /** - * 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. - * - * @private - */ - value: function loadNavigationElements() { - this.cleanNavigation(); + this.iconsCreated = false; + } + }, { + key: 'loadNavigationElements', - this.navigationDOM = {}; - var navigationDivs = ["up", "down", "left", "right", "zoomIn", "zoomOut", "zoomExtends"]; - var navigationDivActions = ["_moveUp", "_moveDown", "_moveLeft", "_moveRight", "_zoomIn", "_zoomOut", "_zoomExtent"]; + /** + * 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. + * + * @private + */ + value: function loadNavigationElements() { + this.cleanNavigation(); - this.navigationDOM.wrapper = document.createElement("div"); - this.canvas.frame.appendChild(this.navigationDOM.wrapper); + this.navigationDOM = {}; + var navigationDivs = ['up', 'down', 'left', 'right', 'zoomIn', 'zoomOut', 'zoomExtends']; + var navigationDivActions = ['_moveUp', '_moveDown', '_moveLeft', '_moveRight', '_zoomIn', '_zoomOut', '_zoomExtent']; - for (var i = 0; i < navigationDivs.length; i++) { - this.navigationDOM[navigationDivs[i]] = document.createElement("div"); - this.navigationDOM[navigationDivs[i]].className = "network-navigation " + navigationDivs[i]; - this.navigationDOM.wrapper.appendChild(this.navigationDOM[navigationDivs[i]]); + this.navigationDOM.wrapper = document.createElement('div'); + this.canvas.frame.appendChild(this.navigationDOM.wrapper); - var hammer = new Hammer(this.navigationDOM[navigationDivs[i]]); - if (navigationDivActions[i] === "_zoomExtent") { - hammerUtil.onTouch(hammer, this._zoomExtent.bind(this)); - } else { - hammerUtil.onTouch(hammer, this.bindToRedraw.bind(this, navigationDivActions[i])); - } + for (var i = 0; i < navigationDivs.length; i++) { + this.navigationDOM[navigationDivs[i]] = document.createElement('div'); + this.navigationDOM[navigationDivs[i]].className = 'network-navigation ' + navigationDivs[i]; + this.navigationDOM.wrapper.appendChild(this.navigationDOM[navigationDivs[i]]); - this.navigationHammers.push(hammer); + var hammer = new Hammer(this.navigationDOM[navigationDivs[i]]); + if (navigationDivActions[i] === '_zoomExtent') { + hammerUtil.onTouch(hammer, this._zoomExtent.bind(this)); + } else { + hammerUtil.onTouch(hammer, this.bindToRedraw.bind(this, navigationDivActions[i])); } - this.iconsCreated = true; - }, - writable: true, - configurable: true - }, - bindToRedraw: { - value: function bindToRedraw(action) { - if (this.boundFunctions[action] === undefined) { - this.boundFunctions[action] = this[action].bind(this); - this.body.emitter.on("initRedraw", this.boundFunctions[action]); - this.body.emitter.emit("_startRendering"); - } - }, - writable: true, - configurable: true - }, - unbindFromRedraw: { - value: function unbindFromRedraw(action) { - if (this.boundFunctions[action] !== undefined) { - this.body.emitter.off("initRedraw", this.boundFunctions[action]); - this.body.emitter.emit("_stopRendering"); - delete this.boundFunctions[action]; - } - }, - writable: true, - configurable: true - }, - _zoomExtent: { + this.navigationHammers.push(hammer); + } - /** - * this stops all movement induced by the navigation buttons - * - * @private - */ - value: function _zoomExtent() { - if (new Date().valueOf() - this.touchTime > 700) { - // TODO: fix ugly hack to avoid hammer's double fireing of event (because we use release?) - this.body.emitter.emit("zoomExtent", { duration: 700 }); - this.touchTime = new Date().valueOf(); - } - }, - writable: true, - configurable: true - }, - _stopMovement: { + this.iconsCreated = true; + } + }, { + key: 'bindToRedraw', + value: function bindToRedraw(action) { + if (this.boundFunctions[action] === undefined) { + this.boundFunctions[action] = this[action].bind(this); + this.body.emitter.on('initRedraw', this.boundFunctions[action]); + this.body.emitter.emit('_startRendering'); + } + } + }, { + key: 'unbindFromRedraw', + value: function unbindFromRedraw(action) { + if (this.boundFunctions[action] !== undefined) { + this.body.emitter.off('initRedraw', this.boundFunctions[action]); + this.body.emitter.emit('_stopRendering'); + delete this.boundFunctions[action]; + } + } + }, { + key: '_zoomExtent', - /** - * this stops all movement induced by the navigation buttons - * - * @private - */ - value: function _stopMovement() { - for (var boundAction in this.boundFunctions) { - if (this.boundFunctions.hasOwnProperty(boundAction)) { - this.body.emitter.off("initRedraw", this.boundFunctions[boundAction]); - this.body.emitter.emit("_stopRendering"); - } - } - this.boundFunctions = {}; - }, - writable: true, - configurable: true - }, - _moveUp: { - value: function _moveUp() { - this.body.view.translation.y += this.options.keyboard.speed.y; - }, - writable: true, - configurable: true - }, - _moveDown: { - value: function _moveDown() { - this.body.view.translation.y -= this.options.keyboard.speed.y; - }, - writable: true, - configurable: true - }, - _moveLeft: { - value: function _moveLeft() { - this.body.view.translation.x += this.options.keyboard.speed.x; - }, - writable: true, - configurable: true - }, - _moveRight: { - value: function _moveRight() { - this.body.view.translation.x -= this.options.keyboard.speed.x; - }, - writable: true, - configurable: true - }, - _zoomIn: { - value: function _zoomIn() { - this.body.view.scale += this.options.keyboard.speed.zoom; - }, - writable: true, - configurable: true - }, - _zoomOut: { - value: function _zoomOut() { - this.body.view.scale -= this.options.keyboard.speed.zoom; - }, - writable: true, - configurable: true - }, - configureKeyboardBindings: { + /** + * this stops all movement induced by the navigation buttons + * + * @private + */ + value: function _zoomExtent() { + if (new Date().valueOf() - this.touchTime > 700) { + // TODO: fix ugly hack to avoid hammer's double fireing of event (because we use release?) + this.body.emitter.emit('zoomExtent', { duration: 700 }); + this.touchTime = new Date().valueOf(); + } + } + }, { + key: '_stopMovement', + /** + * this stops all movement induced by the navigation buttons + * + * @private + */ + value: function _stopMovement() { + for (var boundAction in this.boundFunctions) { + if (this.boundFunctions.hasOwnProperty(boundAction)) { + this.body.emitter.off('initRedraw', this.boundFunctions[boundAction]); + this.body.emitter.emit('_stopRendering'); + } + } + this.boundFunctions = {}; + } + }, { + key: '_moveUp', + value: function _moveUp() { + this.body.view.translation.y += this.options.keyboard.speed.y; + } + }, { + key: '_moveDown', + value: function _moveDown() { + this.body.view.translation.y -= this.options.keyboard.speed.y; + } + }, { + key: '_moveLeft', + value: function _moveLeft() { + this.body.view.translation.x += this.options.keyboard.speed.x; + } + }, { + key: '_moveRight', + value: function _moveRight() { + this.body.view.translation.x -= this.options.keyboard.speed.x; + } + }, { + key: '_zoomIn', + value: function _zoomIn() { + this.body.view.scale += this.options.keyboard.speed.zoom; + } + }, { + key: '_zoomOut', + value: function _zoomOut() { + this.body.view.scale -= this.options.keyboard.speed.zoom; + } + }, { + key: 'configureKeyboardBindings', - /** - * bind all keys using keycharm. - */ - value: function configureKeyboardBindings() { - if (this.keycharm !== undefined) { - this.keycharm.destroy(); - } + /** + * bind all keys using keycharm. + */ + value: function configureKeyboardBindings() { + if (this.keycharm !== undefined) { + this.keycharm.destroy(); + } - if (this.options.keyboard.enabled === true) { - if (this.options.keyboard.bindToWindow === true) { - this.keycharm = keycharm({ container: window, preventDefault: false }); - } else { - this.keycharm = keycharm({ container: this.canvas.frame, preventDefault: false }); - } + if (this.options.keyboard.enabled === true) { - this.keycharm.reset(); - - if (this.activated === true) { - this.keycharm.bind("up", this.bindToRedraw.bind(this, "_moveUp"), "keydown"); - this.keycharm.bind("down", this.bindToRedraw.bind(this, "_moveDown"), "keydown"); - this.keycharm.bind("left", this.bindToRedraw.bind(this, "_moveLeft"), "keydown"); - this.keycharm.bind("right", this.bindToRedraw.bind(this, "_moveRight"), "keydown"); - this.keycharm.bind("=", this.bindToRedraw.bind(this, "_zoomIn"), "keydown"); - this.keycharm.bind("num+", this.bindToRedraw.bind(this, "_zoomIn"), "keydown"); - this.keycharm.bind("num-", this.bindToRedraw.bind(this, "_zoomOut"), "keydown"); - this.keycharm.bind("-", this.bindToRedraw.bind(this, "_zoomOut"), "keydown"); - this.keycharm.bind("[", this.bindToRedraw.bind(this, "_zoomOut"), "keydown"); - this.keycharm.bind("]", this.bindToRedraw.bind(this, "_zoomIn"), "keydown"); - this.keycharm.bind("pageup", this.bindToRedraw.bind(this, "_zoomIn"), "keydown"); - this.keycharm.bind("pagedown", this.bindToRedraw.bind(this, "_zoomOut"), "keydown"); - - this.keycharm.bind("up", this.unbindFromRedraw.bind(this, "_moveUp"), "keyup"); - this.keycharm.bind("down", this.unbindFromRedraw.bind(this, "_moveDown"), "keyup"); - this.keycharm.bind("left", this.unbindFromRedraw.bind(this, "_moveLeft"), "keyup"); - this.keycharm.bind("right", this.unbindFromRedraw.bind(this, "_moveRight"), "keyup"); - this.keycharm.bind("=", this.unbindFromRedraw.bind(this, "_zoomIn"), "keyup"); - this.keycharm.bind("num+", this.unbindFromRedraw.bind(this, "_zoomIn"), "keyup"); - this.keycharm.bind("num-", this.unbindFromRedraw.bind(this, "_zoomOut"), "keyup"); - this.keycharm.bind("-", this.unbindFromRedraw.bind(this, "_zoomOut"), "keyup"); - this.keycharm.bind("[", this.unbindFromRedraw.bind(this, "_zoomOut"), "keyup"); - this.keycharm.bind("]", this.unbindFromRedraw.bind(this, "_zoomIn"), "keyup"); - this.keycharm.bind("pageup", this.unbindFromRedraw.bind(this, "_zoomIn"), "keyup"); - this.keycharm.bind("pagedown", this.unbindFromRedraw.bind(this, "_zoomOut"), "keyup"); - } + if (this.options.keyboard.bindToWindow === true) { + this.keycharm = keycharm({ container: window, preventDefault: false }); + } else { + this.keycharm = keycharm({ container: this.canvas.frame, preventDefault: false }); + } + + this.keycharm.reset(); + + if (this.activated === true) { + this.keycharm.bind('up', this.bindToRedraw.bind(this, '_moveUp'), 'keydown'); + this.keycharm.bind('down', this.bindToRedraw.bind(this, '_moveDown'), 'keydown'); + this.keycharm.bind('left', this.bindToRedraw.bind(this, '_moveLeft'), 'keydown'); + this.keycharm.bind('right', this.bindToRedraw.bind(this, '_moveRight'), 'keydown'); + this.keycharm.bind('=', this.bindToRedraw.bind(this, '_zoomIn'), 'keydown'); + this.keycharm.bind('num+', this.bindToRedraw.bind(this, '_zoomIn'), 'keydown'); + this.keycharm.bind('num-', this.bindToRedraw.bind(this, '_zoomOut'), 'keydown'); + this.keycharm.bind('-', this.bindToRedraw.bind(this, '_zoomOut'), 'keydown'); + this.keycharm.bind('[', this.bindToRedraw.bind(this, '_zoomOut'), 'keydown'); + this.keycharm.bind(']', this.bindToRedraw.bind(this, '_zoomIn'), 'keydown'); + this.keycharm.bind('pageup', this.bindToRedraw.bind(this, '_zoomIn'), 'keydown'); + this.keycharm.bind('pagedown', this.bindToRedraw.bind(this, '_zoomOut'), 'keydown'); + + this.keycharm.bind('up', this.unbindFromRedraw.bind(this, '_moveUp'), 'keyup'); + this.keycharm.bind('down', this.unbindFromRedraw.bind(this, '_moveDown'), 'keyup'); + this.keycharm.bind('left', this.unbindFromRedraw.bind(this, '_moveLeft'), 'keyup'); + this.keycharm.bind('right', this.unbindFromRedraw.bind(this, '_moveRight'), 'keyup'); + this.keycharm.bind('=', this.unbindFromRedraw.bind(this, '_zoomIn'), 'keyup'); + this.keycharm.bind('num+', this.unbindFromRedraw.bind(this, '_zoomIn'), 'keyup'); + this.keycharm.bind('num-', this.unbindFromRedraw.bind(this, '_zoomOut'), 'keyup'); + this.keycharm.bind('-', this.unbindFromRedraw.bind(this, '_zoomOut'), 'keyup'); + this.keycharm.bind('[', this.unbindFromRedraw.bind(this, '_zoomOut'), 'keyup'); + this.keycharm.bind(']', this.unbindFromRedraw.bind(this, '_zoomIn'), 'keyup'); + this.keycharm.bind('pageup', this.unbindFromRedraw.bind(this, '_zoomIn'), 'keyup'); + this.keycharm.bind('pagedown', this.unbindFromRedraw.bind(this, '_zoomOut'), 'keyup'); } - }, - writable: true, - configurable: true + } } - }); + }]); return NavigationHandler; })(); - module.exports = NavigationHandler; + exports['default'] = NavigationHandler; + module.exports = exports['default']; /***/ }, -/* 79 */ +/* 78 */ /***/ function(module, exports, __webpack_require__) { "use strict"; - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + Object.defineProperty(exports, "__esModule", { + value: true + }); /** * Popup is a class to create a popup window with some text * @param {Element} container The container object. @@ -32482,6 +34009,7 @@ return /******/ (function(modules) { // webpackBootstrap * @param {Object} [style] An object containing borderColor, * backgroundColor, etc. */ + var Popup = (function () { function Popup(container, x, y, text, style) { _classCallCheck(this, Popup); @@ -32537,2553 +34065,3196 @@ return /******/ (function(modules) { // webpackBootstrap this.container.appendChild(this.frame); } - _prototypeProperties(Popup, null, { - setPosition: { + _createClass(Popup, [{ + key: "setPosition", - /** - * @param {number} x Horizontal position of the popup window - * @param {number} y Vertical position of the popup window - */ - value: function setPosition(x, y) { - this.x = parseInt(x); - this.y = parseInt(y); - }, - writable: true, - configurable: true - }, - setText: { - - /** - * Set the content for the popup window. This can be HTML code or text. - * @param {string | Element} content - */ - value: function setText(content) { - if (content instanceof Element) { - this.frame.innerHTML = ""; - this.frame.appendChild(content); - } else { - this.frame.innerHTML = content; // string containing text or HTML - } - }, - writable: true, - configurable: true - }, - show: { + /** + * @param {number} x Horizontal position of the popup window + * @param {number} y Vertical position of the popup window + */ + value: function setPosition(x, y) { + this.x = parseInt(x); + this.y = parseInt(y); + } + }, { + key: "setText", - /** - * Show the popup window - * @param {boolean} [doShow] Show or hide the window - */ - value: function show(doShow) { - if (doShow === undefined) { - doShow = true; - } + /** + * Set the content for the popup window. This can be HTML code or text. + * @param {string | Element} content + */ + value: function setText(content) { + if (content instanceof Element) { + this.frame.innerHTML = ""; + this.frame.appendChild(content); + } else { + this.frame.innerHTML = content; // string containing text or HTML + } + } + }, { + key: "show", - if (doShow === true) { - var height = this.frame.clientHeight; - var width = this.frame.clientWidth; - var maxHeight = this.frame.parentNode.clientHeight; - var maxWidth = this.frame.parentNode.clientWidth; + /** + * Show the popup window + * @param {boolean} [doShow] Show or hide the window + */ + value: function show(doShow) { + if (doShow === undefined) { + doShow = true; + } - var top = this.y - height; - if (top + height + this.padding > maxHeight) { - top = maxHeight - height - this.padding; - } - if (top < this.padding) { - top = this.padding; - } + if (doShow === true) { + var height = this.frame.clientHeight; + var width = this.frame.clientWidth; + var maxHeight = this.frame.parentNode.clientHeight; + var maxWidth = this.frame.parentNode.clientWidth; - var left = this.x; - if (left + width + this.padding > maxWidth) { - left = maxWidth - width - this.padding; - } - if (left < this.padding) { - left = this.padding; - } + var top = this.y - height; + if (top + height + this.padding > maxHeight) { + top = maxHeight - height - this.padding; + } + if (top < this.padding) { + top = 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(); + var left = this.x; + if (left + width + this.padding > maxWidth) { + left = maxWidth - width - this.padding; + } + if (left < this.padding) { + left = this.padding; } - }, - writable: true, - configurable: true - }, - hide: { - /** - * Hide the popup window - */ - value: function hide() { - this.hidden = true; - this.frame.style.visibility = "hidden"; - }, - writable: true, - configurable: true + this.frame.style.left = left + "px"; + this.frame.style.top = top + "px"; + this.frame.style.visibility = "visible"; + this.hidden = false; + } else { + this.hide(); + } } - }); + }, { + key: "hide", + + /** + * Hide the popup window + */ + value: function hide() { + this.hidden = true; + this.frame.style.visibility = "hidden"; + } + }]); return Popup; })(); - module.exports = Popup; + exports["default"] = Popup; + module.exports = exports["default"]; /***/ }, -/* 80 */ +/* 79 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + // English + 'use strict'; + + 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.', + editClusterError: 'Clusters cannot be edited.' + }; + 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.', + editClusterError: 'Clusters kunnen niet worden aangepast.' + }; + exports.nl_NL = exports.nl; + exports.nl_BE = exports.nl; - var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; +/***/ }, +/* 80 */ +/***/ function(module, exports, __webpack_require__) { - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; + 'use strict'; - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + Object.defineProperty(exports, '__esModule', { + value: true + }); + var Hammer = __webpack_require__(41); + var hammerUtil = __webpack_require__(44); var util = __webpack_require__(1); - var Label = _interopRequire(__webpack_require__(81)); + var ColorPicker = (function () { + function ColorPicker() { + var pixelRatio = arguments[0] === undefined ? 1 : arguments[0]; + + _classCallCheck(this, ColorPicker); + + this.pixelRatio = pixelRatio; + this.generated = false; + this.centerCoordinates = { x: 289 / 2, y: 289 / 2 }; + this.r = 289 * 0.49; + this.color = { r: 255, g: 255, b: 255, a: 1 }; + this.hueCircle = undefined; + this.initialColor = { r: 255, g: 255, b: 255, a: 1 }; + this.previousColor = undefined; + this.applied = false; + + // bound by + this.updateCallback = function () {}; + + // create all DOM elements + this._create(); + } + + _createClass(ColorPicker, [{ + key: 'insertTo', + + /** + * this inserts the colorPicker into a div from the DOM + * @param container + */ + value: function insertTo(container) { + if (this.hammer !== undefined) { + this.hammer.destroy(); + this.hammer = undefined; + } + this.container = container; + this.container.appendChild(this.frame); + this._bindHammer(); + + this._setSize(); + } + }, { + key: 'setCallback', + + /** + * the callback is executed on apply and save. Bind it to the application + * @param callback + */ + value: function setCallback(callback) { + if (typeof callback === 'function') { + this.updateCallback = callback; + } else { + throw new Error('Function attempted to set as colorPicker callback is not a function.'); + } + } + }, { + key: '_isColorString', + value: function _isColorString(color) { + var htmlColors = { black: '#000000', navy: '#000080', darkblue: '#00008B', mediumblue: '#0000CD', blue: '#0000FF', darkgreen: '#006400', green: '#008000', teal: '#008080', darkcyan: '#008B8B', deepskyblue: '#00BFFF', darkturquoise: '#00CED1', mediumspringgreen: '#00FA9A', lime: '#00FF00', springgreen: '#00FF7F', aqua: '#00FFFF', cyan: '#00FFFF', midnightblue: '#191970', dodgerblue: '#1E90FF', lightseagreen: '#20B2AA', forestgreen: '#228B22', seagreen: '#2E8B57', darkslategray: '#2F4F4F', limegreen: '#32CD32', mediumseagreen: '#3CB371', turquoise: '#40E0D0', royalblue: '#4169E1', steelblue: '#4682B4', darkslateblue: '#483D8B', mediumturquoise: '#48D1CC', indigo: '#4B0082', darkolivegreen: '#556B2F', cadetblue: '#5F9EA0', cornflowerblue: '#6495ED', mediumaquamarine: '#66CDAA', dimgray: '#696969', slateblue: '#6A5ACD', olivedrab: '#6B8E23', slategray: '#708090', lightslategray: '#778899', mediumslateblue: '#7B68EE', lawngreen: '#7CFC00', chartreuse: '#7FFF00', aquamarine: '#7FFFD4', maroon: '#800000', purple: '#800080', olive: '#808000', gray: '#808080', skyblue: '#87CEEB', lightskyblue: '#87CEFA', blueviolet: '#8A2BE2', darkred: '#8B0000', darkmagenta: '#8B008B', saddlebrown: '#8B4513', darkseagreen: '#8FBC8F', lightgreen: '#90EE90', mediumpurple: '#9370D8', darkviolet: '#9400D3', palegreen: '#98FB98', darkorchid: '#9932CC', yellowgreen: '#9ACD32', sienna: '#A0522D', brown: '#A52A2A', darkgray: '#A9A9A9', lightblue: '#ADD8E6', greenyellow: '#ADFF2F', paleturquoise: '#AFEEEE', lightsteelblue: '#B0C4DE', powderblue: '#B0E0E6', firebrick: '#B22222', darkgoldenrod: '#B8860B', mediumorchid: '#BA55D3', rosybrown: '#BC8F8F', darkkhaki: '#BDB76B', silver: '#C0C0C0', mediumvioletred: '#C71585', indianred: '#CD5C5C', peru: '#CD853F', chocolate: '#D2691E', tan: '#D2B48C', lightgrey: '#D3D3D3', palevioletred: '#D87093', thistle: '#D8BFD8', orchid: '#DA70D6', goldenrod: '#DAA520', crimson: '#DC143C', gainsboro: '#DCDCDC', plum: '#DDA0DD', burlywood: '#DEB887', lightcyan: '#E0FFFF', lavender: '#E6E6FA', darksalmon: '#E9967A', violet: '#EE82EE', palegoldenrod: '#EEE8AA', lightcoral: '#F08080', khaki: '#F0E68C', aliceblue: '#F0F8FF', honeydew: '#F0FFF0', azure: '#F0FFFF', sandybrown: '#F4A460', wheat: '#F5DEB3', beige: '#F5F5DC', whitesmoke: '#F5F5F5', mintcream: '#F5FFFA', ghostwhite: '#F8F8FF', salmon: '#FA8072', antiquewhite: '#FAEBD7', linen: '#FAF0E6', lightgoldenrodyellow: '#FAFAD2', oldlace: '#FDF5E6', red: '#FF0000', fuchsia: '#FF00FF', magenta: '#FF00FF', deeppink: '#FF1493', orangered: '#FF4500', tomato: '#FF6347', hotpink: '#FF69B4', coral: '#FF7F50', darkorange: '#FF8C00', lightsalmon: '#FFA07A', orange: '#FFA500', lightpink: '#FFB6C1', pink: '#FFC0CB', gold: '#FFD700', peachpuff: '#FFDAB9', navajowhite: '#FFDEAD', moccasin: '#FFE4B5', bisque: '#FFE4C4', mistyrose: '#FFE4E1', blanchedalmond: '#FFEBCD', papayawhip: '#FFEFD5', lavenderblush: '#FFF0F5', seashell: '#FFF5EE', cornsilk: '#FFF8DC', lemonchiffon: '#FFFACD', floralwhite: '#FFFAF0', snow: '#FFFAFA', yellow: '#FFFF00', lightyellow: '#FFFFE0', ivory: '#FFFFF0', white: '#FFFFFF' }; + if (typeof color === 'string') { + return htmlColors[color]; + } + } + }, { + key: 'setColor', + + /** + * Set the color of the colorPicker + * Supported formats: + * 'red' --> HTML color string + * '#ffffff' --> hex string + * 'rbg(255,255,255)' --> rgb string + * 'rgba(255,255,255,1.0)' --> rgba string + * {r:255,g:255,b:255} --> rgb object + * {r:255,g:255,b:255,a:1.0} --> rgba object + * @param color + * @param setInitial + */ + value: function setColor(color) { + var setInitial = arguments[1] === undefined ? true : arguments[1]; + + if (color === 'none') { + return; + } + + var rgba = undefined; + + // if a html color shorthand is used, convert to hex + var htmlColor = this._isColorString(color); + if (htmlColor !== undefined) { + color = htmlColor; + } + + // check format + if (util.isString(color) === true) { + if (util.isValidRGB(color) === true) { + var rgbaArray = color.substr(4).substr(0, color.length - 5).split(','); + rgba = { r: rgbaArray[0], g: rgbaArray[1], b: rgbaArray[2], a: 1 }; + } else if (util.isValidRGBA(color) === true) { + var rgbaArray = color.substr(5).substr(0, color.length - 6).split(','); + rgba = { r: rgbaArray[0], g: rgbaArray[1], b: rgbaArray[2], a: rgbaArray[3] }; + } else if (util.isValidHex(color) === true) { + var rgbObj = util.hexToRGB(color); + rgba = { r: rgbObj.r, g: rgbObj.g, b: rgbObj.b, a: 1 }; + } + } else { + if (color instanceof Object) { + if (color.r !== undefined && color.g !== undefined && color.b !== undefined) { + var alpha = color.a !== undefined ? color.a : '1.0'; + rgba = { r: color.r, g: color.g, b: color.b, a: alpha }; + } + } + } + + // set color + if (rgba === undefined) { + throw new Error('Unknown color passed to the colorPicker. Supported are strings: rgb, hex, rgba. Object: rgb ({r:r,g:g,b:b,[a:a]}). Supplied: ' + JSON.stringify(color)); + } else { + this._setColor(rgba, setInitial); + } + } + }, { + key: 'show', + + /** + * this shows the color picker at a location. The hue circle is constructed once and stored. + * @param x + * @param y + */ + value: function show(x, y) { + this.applied = false; + this.frame.style.display = 'block'; + this.frame.style.top = y + 'px'; + this.frame.style.left = x + 'px'; + this._generateHueCircle(); + } + }, { + key: '_hide', + + // ------------------------------------------ PRIVATE ----------------------------- // + + /** + * Hide the picker. Is called by the cancel button. + * Optional boolean to store the previous color for easy access later on. + * @param storePrevious + * @private + */ + value: function _hide() { + var storePrevious = arguments[0] === undefined ? true : arguments[0]; + + // store the previous color for next time; + if (storePrevious === true) { + this.previousColor = util.extend({}, this.color); + } + + if (this.applied === true) { + this.updateCallback(this.initialColor); + } + + this.frame.style.display = 'none'; + } + }, { + key: '_save', + + /** + * bound to the save button. Saves and hides. + * @private + */ + value: function _save() { + this.updateCallback(this.color); + this.applied = false; + this._hide(); + } + }, { + key: '_apply', + + /** + * Bound to apply button. Saves but does not close. Is undone by the cancel button. + * @private + */ + value: function _apply() { + this.applied = true; + this.updateCallback(this.color); + this._updatePicker(this.color); + } + }, { + key: '_loadLast', + + /** + * load the color from the previous session. + * @private + */ + value: function _loadLast() { + if (this.previousColor !== undefined) { + this.setColor(this.previousColor, false); + } else { + alert('There is no last color to load...'); + } + } + }, { + key: '_setColor', + + /** + * set the color, place the picker + * @param rgba + * @param setInitial + * @private + */ + value: function _setColor(rgba) { + var setInitial = arguments[1] === undefined ? true : arguments[1]; + + // store the initial color + if (setInitial === true) { + this.initialColor = util.extend({}, rgba); + } + + this.color = rgba; + var hsv = util.RGBToHSV(rgba.r, rgba.g, rgba.b); + + var angleConvert = 2 * Math.PI; + var radius = this.r * hsv.s; + var x = this.centerCoordinates.x + radius * Math.sin(angleConvert * hsv.h); + var y = this.centerCoordinates.y + radius * Math.cos(angleConvert * hsv.h); + + this.colorPickerSelector.style.left = x - 0.5 * this.colorPickerSelector.clientWidth + 'px'; + this.colorPickerSelector.style.top = y - 0.5 * this.colorPickerSelector.clientHeight + 'px'; + + this._updatePicker(rgba); + } + }, { + key: '_setOpacity', + + /** + * bound to opacity control + * @param value + * @private + */ + value: function _setOpacity(value) { + this.color.a = value / 100; + this._updatePicker(this.color); + } + }, { + key: '_setBrightness', + + /** + * bound to brightness control + * @param value + * @private + */ + value: function _setBrightness(value) { + var hsv = util.RGBToHSV(this.color.r, this.color.g, this.color.b); + hsv.v = value / 100; + var rgba = util.HSVToRGB(hsv.h, hsv.s, hsv.v); + rgba.a = this.color.a; + this.color = rgba; + this._updatePicker(); + } + }, { + key: '_updatePicker', + + /** + * update the colorpicker. A black circle overlays the hue circle to mimic the brightness decreasing. + * @param rgba + * @private + */ + value: function _updatePicker() { + var rgba = arguments[0] === undefined ? this.color : arguments[0]; + + var hsv = util.RGBToHSV(rgba.r, rgba.g, rgba.b); + var ctx = this.colorPickerCanvas.getContext('2d'); + if (this.pixelRation === undefined) { + this.pixelRatio = (window.devicePixelRatio || 1) / (ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1); + } + ctx.setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0); + + // clear the canvas + var w = this.colorPickerCanvas.clientWidth; + var h = this.colorPickerCanvas.clientHeight; + ctx.clearRect(0, 0, w, h); + + ctx.putImageData(this.hueCircle, 0, 0); + ctx.fillStyle = 'rgba(0,0,0,' + (1 - hsv.v) + ')'; + ctx.circle(this.centerCoordinates.x, this.centerCoordinates.y, this.r); + ctx.fill(); + + this.brightnessRange.value = 100 * hsv.v; + this.opacityRange.value = 100 * rgba.a; + + this.initialColorDiv.style.backgroundColor = 'rgba(' + this.initialColor.r + ',' + this.initialColor.g + ',' + this.initialColor.b + ',' + this.initialColor.a + ')'; + this.newColorDiv.style.backgroundColor = 'rgba(' + this.color.r + ',' + this.color.g + ',' + this.color.b + ',' + this.color.a + ')'; + } + }, { + key: '_setSize', + + /** + * used by create to set the size of the canvas. + * @private + */ + value: function _setSize() { + this.colorPickerCanvas.style.width = '100%'; + this.colorPickerCanvas.style.height = '100%'; + + this.colorPickerCanvas.width = 289 * this.pixelRatio; + this.colorPickerCanvas.height = 289 * this.pixelRatio; + } + }, { + key: '_create', + + /** + * create all dom elements + * TODO: cleanup, lots of similar dom elements + * @private + */ + value: function _create() { + var visPrefix = 'vis-network-'; + + this.frame = document.createElement('div'); + this.frame.className = visPrefix + 'colorPicker-frame'; + + this.colorPickerDiv = document.createElement('div'); + this.colorPickerSelector = document.createElement('div'); + this.colorPickerSelector.className = visPrefix + 'colorPicker-selector'; + this.colorPickerDiv.appendChild(this.colorPickerSelector); + + this.colorPickerCanvas = document.createElement('canvas'); + this.colorPickerDiv.appendChild(this.colorPickerCanvas); + + if (!this.colorPickerCanvas.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.colorPickerCanvas.appendChild(noCanvas); + } else { + var ctx = this.colorPickerCanvas.getContext('2d'); + this.pixelRatio = (window.devicePixelRatio || 1) / (ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1); + + this.colorPickerCanvas.getContext('2d').setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0); + } + + this.colorPickerDiv.className = visPrefix + 'colorPicker-color'; + + this.opacityDiv = document.createElement('div'); + this.opacityDiv.className = visPrefix + 'colorPicker-opacity'; + + this.brightnessDiv = document.createElement('div'); + this.brightnessDiv.className = visPrefix + 'colorPicker-brightness'; + + this.arrowDiv = document.createElement('div'); + this.arrowDiv.className = visPrefix + 'colorPicker-arrowDiv'; + + this.opacityRange = document.createElement('input'); + this.opacityRange.type = 'range'; + this.opacityRange.min = '0'; + this.opacityRange.max = '100'; + this.opacityRange.value = '100'; + this.opacityRange.className = visPrefix + 'configuration range colorPicker'; + + this.brightnessRange = document.createElement('input'); + this.brightnessRange.type = 'range'; + this.brightnessRange.min = '0'; + this.brightnessRange.max = '100'; + this.brightnessRange.value = '100'; + this.brightnessRange.className = visPrefix + 'configuration range colorPicker'; + + this.opacityDiv.appendChild(this.opacityRange); + this.brightnessDiv.appendChild(this.brightnessRange); + + var me = this; + this.opacityRange.onchange = function () { + me._setOpacity(this.value); + }; + this.opacityRange.oninput = function () { + me._setOpacity(this.value); + }; + this.brightnessRange.onchange = function () { + me._setBrightness(this.value); + }; + this.brightnessRange.oninput = function () { + me._setBrightness(this.value); + }; + + this.brightnessLabel = document.createElement('div'); + this.brightnessLabel.className = visPrefix + 'colorPicker-label brightness'; + this.brightnessLabel.innerHTML = 'brightness:'; + + this.opacityLabel = document.createElement('div'); + this.opacityLabel.className = visPrefix + 'colorPicker-label opacity'; + this.opacityLabel.innerHTML = 'opacity:'; + + this.newColorDiv = document.createElement('div'); + this.newColorDiv.className = visPrefix + 'colorPicker-newColor'; + this.newColorDiv.innerHTML = 'new'; + + this.initialColorDiv = document.createElement('div'); + this.initialColorDiv.className = visPrefix + 'colorPicker-initialColor'; + this.initialColorDiv.innerHTML = 'initial'; + + this.cancelButton = document.createElement('div'); + this.cancelButton.className = visPrefix + 'colorPicker-button cancel'; + this.cancelButton.innerHTML = 'cancel'; + this.cancelButton.onclick = this._hide.bind(this, false); + + this.applyButton = document.createElement('div'); + this.applyButton.className = visPrefix + 'colorPicker-button apply'; + this.applyButton.innerHTML = 'apply'; + this.applyButton.onclick = this._apply.bind(this); + + this.saveButton = document.createElement('div'); + this.saveButton.className = visPrefix + 'colorPicker-button save'; + this.saveButton.innerHTML = 'save'; + this.saveButton.onclick = this._save.bind(this); + + this.loadButton = document.createElement('div'); + this.loadButton.className = visPrefix + 'colorPicker-button load'; + this.loadButton.innerHTML = 'load last'; + this.loadButton.onclick = this._loadLast.bind(this); + + this.frame.appendChild(this.colorPickerDiv); + this.frame.appendChild(this.arrowDiv); + this.frame.appendChild(this.brightnessLabel); + this.frame.appendChild(this.brightnessDiv); + this.frame.appendChild(this.opacityLabel); + this.frame.appendChild(this.opacityDiv); + this.frame.appendChild(this.newColorDiv); + this.frame.appendChild(this.initialColorDiv); + + this.frame.appendChild(this.cancelButton); + this.frame.appendChild(this.applyButton); + this.frame.appendChild(this.saveButton); + this.frame.appendChild(this.loadButton); + } + }, { + key: '_bindHammer', + + /** + * bind hammer to the color picker + * @private + */ + value: function _bindHammer() { + var _this = this; + + this.drag = {}; + this.pinch = {}; + this.hammer = new Hammer(this.colorPickerCanvas); + this.hammer.get('pinch').set({ enable: true }); + + hammerUtil.onTouch(this.hammer, function (event) { + _this._moveSelector(event); + }); + this.hammer.on('tap', function (event) { + _this._moveSelector(event); + }); + this.hammer.on('panstart', function (event) { + _this._moveSelector(event); + }); + this.hammer.on('panmove', function (event) { + _this._moveSelector(event); + }); + this.hammer.on('panend', function (event) { + _this._moveSelector(event); + }); + } + }, { + key: '_generateHueCircle', - var Box = _interopRequire(__webpack_require__(82)); + /** + * generate the hue circle. This is relatively heavy (200ms) and is done only once on the first time it is shown. + * @private + */ + value: function _generateHueCircle() { + if (this.generated === false) { + var ctx = this.colorPickerCanvas.getContext('2d'); + if (this.pixelRation === undefined) { + this.pixelRatio = (window.devicePixelRatio || 1) / (ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1); + } + ctx.setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0); + + // clear the canvas + var w = this.colorPickerCanvas.clientWidth; + var h = this.colorPickerCanvas.clientHeight; + ctx.clearRect(0, 0, w, h); - var Circle = _interopRequire(__webpack_require__(83)); + // draw hue circle + var x = undefined, + y = undefined, + hue = undefined, + sat = undefined; + this.centerCoordinates = { x: w * 0.5, y: h * 0.5 }; + this.r = 0.49 * w; + var angleConvert = 2 * Math.PI / 360; + var hfac = 1 / 360; + var sfac = 1 / this.r; + var rgb = undefined; + for (hue = 0; hue < 360; hue++) { + for (sat = 0; sat < this.r; sat++) { + x = this.centerCoordinates.x + sat * Math.sin(angleConvert * hue); + y = this.centerCoordinates.y + sat * Math.cos(angleConvert * hue); + rgb = util.HSVToRGB(hue * hfac, sat * sfac, 1); + ctx.fillStyle = 'rgb(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ')'; + ctx.fillRect(x - 0.5, y - 0.5, 2, 2); + } + } + ctx.strokeStyle = 'rgba(0,0,0,1)'; + ctx.circle(this.centerCoordinates.x, this.centerCoordinates.y, this.r); + ctx.stroke(); - var CircularImage = _interopRequire(__webpack_require__(84)); + this.hueCircle = ctx.getImageData(0, 0, w, h); + } + this.generated = true; + } + }, { + key: '_moveSelector', - var Database = _interopRequire(__webpack_require__(85)); + /** + * move the selector. This is called by hammer functions. + * + * @param event + * @private + */ + value: function _moveSelector(event) { + var rect = this.colorPickerDiv.getBoundingClientRect(); + var left = event.center.x - rect.left; + var top = event.center.y - rect.top; - var Diamond = _interopRequire(__webpack_require__(86)); + var centerY = 0.5 * this.colorPickerDiv.clientHeight; + var centerX = 0.5 * this.colorPickerDiv.clientWidth; - var Dot = _interopRequire(__webpack_require__(87)); + var x = left - centerX; + var y = top - centerY; - var Ellipse = _interopRequire(__webpack_require__(88)); + var angle = Math.atan2(x, y); + var radius = 0.98 * Math.min(Math.sqrt(x * x + y * y), centerX); - var Icon = _interopRequire(__webpack_require__(89)); + var newTop = Math.cos(angle) * radius + centerY; + var newLeft = Math.sin(angle) * radius + centerX; - var Image = _interopRequire(__webpack_require__(90)); + this.colorPickerSelector.style.top = newTop - 0.5 * this.colorPickerSelector.clientHeight + 'px'; + this.colorPickerSelector.style.left = newLeft - 0.5 * this.colorPickerSelector.clientWidth + 'px'; - var Square = _interopRequire(__webpack_require__(91)); + // set color + var h = angle / (2 * Math.PI); + h = h < 0 ? h + 1 : h; + var s = radius / this.r; + var hsv = util.RGBToHSV(this.color.r, this.color.g, this.color.b); + hsv.h = h; + hsv.s = s; + var rgba = util.HSVToRGB(hsv.h, hsv.s, hsv.v); + rgba.a = this.color.a; + this.color = rgba; - var Star = _interopRequire(__webpack_require__(92)); + // update previews + this.initialColorDiv.style.backgroundColor = 'rgba(' + this.initialColor.r + ',' + this.initialColor.g + ',' + this.initialColor.b + ',' + this.initialColor.a + ')'; + this.newColorDiv.style.backgroundColor = 'rgba(' + this.color.r + ',' + this.color.g + ',' + this.color.b + ',' + this.color.a + ')'; + } + }]); - var Text = _interopRequire(__webpack_require__(93)); + return ColorPicker; + })(); - var Triangle = _interopRequire(__webpack_require__(94)); + exports['default'] = ColorPicker; + module.exports = exports['default']; - var TriangleDown = _interopRequire(__webpack_require__(95)); +/***/ }, +/* 81 */ +/***/ function(module, exports, __webpack_require__) { + var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;"use strict"; /** - * @class Node - * A node. A node can be connected to other nodes via one or multiple edges. - * @param {object} options An object containing options for the node. All - * options 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 options - * @param {Object} constants An object with default values for - * example for the color - * + * Created by Alex on 11/6/2014. */ - var Node = (function () { - function Node(options, body, imagelist, grouplist, globalOptions) { - _classCallCheck(this, Node); - - this.options = util.bridgeObject(globalOptions); - this.body = body; - - this.edges = []; // all edges connected to this node - - // set defaults for the options - this.id = undefined; - this.imagelist = imagelist; - this.grouplist = grouplist; - - // state options - this.x = undefined; - this.y = undefined; - this.predefinedPosition = false; // used to check if initial zoomExtent should just take the range or approximate - this.selected = false; - this.hover = false; - this.labelModule = new Label(this.body, this.options); - this.setOptions(options); + // 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 () { - _prototypeProperties(Node, null, { - attachEdge: { + 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; - /** - * Attach a edge to the node - * @param {Edge} edge - */ - value: function attachEdge(edge) { - if (this.edges.indexOf(edge) === -1) { - this.edges.push(edge); - } - }, - writable: true, - configurable: true - }, - detachEdge: { + // 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}; - /** - * Detach a edge from the node - * @param {Edge} edge - */ - value: function detachEdge(edge) { - var index = this.edges.indexOf(edge); - if (index != -1) { - this.edges.splice(index, 1); - } - }, - writable: true, - configurable: true - }, - togglePhysics: { - /** - * Enable or disable the physics. - * @param status - */ - value: function togglePhysics(status) { - this.options.physics = status; - }, - writable: true, - configurable: true - }, - setOptions: { + var down = function(event) {handleEvent(event,'keydown');}; + var up = function(event) {handleEvent(event,'keyup');}; - /** - * Set or overwrite options for the node - * @param {Object} options an object with options - * @param {Object} constants and object with default, global options - */ - value: function setOptions(options) { - if (!options) { - return; + // 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); + } } - var fields = ["borderWidth", "borderWidthSelected", "brokenImage", "customScalingFunction", "font", "hidden", "icon", "id", "image", "label", "level", "physics", "shape", "size", "title", "value", "x", "y"]; - util.selectiveDeepExtend(fields, this.options, options); - - // basic options - if (options.id !== undefined) { - this.id = options.id; + if (preventDefault == true) { + event.preventDefault(); } + } + }; - if (this.id === undefined) { - throw "Node must have an id"; - } + // 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}); + }; - if (options.x !== undefined) { - this.x = options.x;this.predefinedPosition = true; - } - if (options.y !== undefined) { - this.y = options.y;this.predefinedPosition = true; - } - if (options.value !== undefined) { - this.value = options.value; - } - // copy group options - if (typeof options.group === "number" || typeof options.group === "string" && options.group != "") { - var groupObj = this.grouplist.get(options.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 options - if (options.color !== undefined) { - this.options.color = util.parseColor(options.color); + // 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); } + } + }; - 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"; + // 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"; + }; - if (options.fixed !== undefined) { - if (typeof options.fixed === "boolean") { - this.options.fixed.x = true; - this.options.fixed.y = true; - } else { - if (options.fixed.x !== undefined && typeof options.fixed.x === "boolean") { - this.options.fixed.x = options.fixed.x; - } - if (options.fixed.y !== undefined && typeof options.fixed.y === "boolean") { - this.options.fixed.y = options.fixed.y; + // 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:{}}; + }; - this.updateShape(); - this.updateLabelModule(); + // unbind all listeners and reset all variables. + _exportFunctions.destroy = function() { + _bound = {keydown:{}, keyup:{}}; + container.removeEventListener('keydown', down, true); + container.removeEventListener('keyup', up, true); + }; - // reset the size of the node, this can be changed - this._reset(); - }, - writable: true, - configurable: true - }, - updateLabelModule: { - value: function updateLabelModule() { - this.labelModule.setOptions(this.options); - }, - writable: true, - configurable: true - }, - updateShape: { - value: function updateShape() { - // choose draw method depending on the shape - switch (this.options.shape) { - case "box": - this.shape = new Box(this.options, this.body, this.labelModule); - break; - case "circle": - this.shape = new Circle(this.options, this.body, this.labelModule); - break; - case "circularImage": - this.shape = new CircularImage(this.options, this.body, this.labelModule, this.imageObj); - break; - case "database": - this.shape = new Database(this.options, this.body, this.labelModule); - break; - case "diamond": - this.shape = new Diamond(this.options, this.body, this.labelModule); - break; - case "dot": - this.shape = new Dot(this.options, this.body, this.labelModule); - break; - case "ellipse": - this.shape = new Ellipse(this.options, this.body, this.labelModule); - break; - case "icon": - this.shape = new Icon(this.options, this.body, this.labelModule); - break; - case "image": - this.shape = new Image(this.options, this.body, this.labelModule, this.imageObj); - break; - case "square": - this.shape = new Square(this.options, this.body, this.labelModule); - break; - case "star": - this.shape = new Star(this.options, this.body, this.labelModule); - break; - case "text": - this.shape = new Text(this.options, this.body, this.labelModule); - break; - case "triangle": - this.shape = new Triangle(this.options, this.body, this.labelModule); - break; - case "triangleDown": - this.shape = new TriangleDown(this.options, this.body, this.labelModule); - break; - default: - this.shape = new Ellipse(this.options, this.body, this.labelModule); - break; - } - this._reset(); - }, - writable: true, - configurable: true - }, - select: { + // create listeners. + container.addEventListener('keydown',down,true); + container.addEventListener('keyup',up,true); + // return the public functions. + return _exportFunctions; + } - /** - * select this node - */ - value: function select() { - this.selected = true; - this._reset(); - }, - writable: true, - configurable: true - }, - unselect: { + return keycharm; + })); - /** - * unselect this node - */ - value: function unselect() { - this.selected = false; - this._reset(); - }, - writable: true, - configurable: true - }, - _reset: { +/***/ }, +/* 82 */ +/***/ function(module, exports, __webpack_require__) { - /** - * Reset the calculated size of the node, forces it to recalculate its size - * @private - */ - value: function _reset() { - this.shape.width = undefined; - this.shape.height = undefined; - }, - writable: true, - configurable: true - }, - getTitle: { + function webpackContext(req) { + throw new Error("Cannot find module '" + req + "'."); + } + webpackContext.keys = function() { return []; }; + webpackContext.resolve = webpackContext; + module.exports = webpackContext; + webpackContext.id = 82; - /** - * get the title of this node. - * @return {string} title The title of the node, or undefined when no title - * has been set. - */ - value: function getTitle() { - return typeof this.options.title === "function" ? this.options.title() : this.options.title; - }, - writable: true, - configurable: true - }, - distanceToBorder: { +/***/ }, +/* 83 */ +/***/ function(module, exports, __webpack_require__) { + module.exports = function(module) { + if(!module.webpackPolyfill) { + module.deprecate = function() {}; + module.paths = []; + // module.parent = undefined by default + module.children = []; + module.webpackPolyfill = 1; + } + return module; + } - /** - * 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 - */ - value: function distanceToBorder(ctx, angle) { - return this.shape.distanceToBorder(ctx, angle); - }, - writable: true, - configurable: true - }, - isFixed: { +/***/ }, +/* 84 */ +/***/ function(module, exports, __webpack_require__) { - /** - * Check if this node has a fixed x and y position - * @return {boolean} true if fixed, false if not - */ - value: function isFixed() { - return this.options.fixed.x && this.options.fixed.y; - }, - writable: true, - configurable: true - }, - isSelected: { + /* WEBPACK VAR INJECTION */(function(__webpack_amd_options__) {module.exports = __webpack_amd_options__; + /* WEBPACK VAR INJECTION */}.call(exports, {})) - /** - * check if this node is selecte - * @return {boolean} selected True if node is selected, else false - */ - value: function isSelected() { - return this.selected; - }, - writable: true, - configurable: true - }, - getValue: { +/***/ }, +/* 85 */ +/***/ function(module, exports, __webpack_require__) { + 'use strict'; - /** - * Retrieve the value of the node. Can be undefined - * @return {Number} value - */ - value: function getValue() { - return this.value; - }, - writable: true, - configurable: true - }, - setValueRange: { + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; - /** - * Adjust the value range of the node. The node will adjust it's size - * based on its value. - * @param {Number} min - * @param {Number} max - */ - value: function setValueRange(min, max, total) { - if (this.value !== undefined) { - var scale = this.options.scaling.customScalingFunction(min, max, total, this.value); - var sizeDiff = this.options.scaling.max - this.options.scaling.min; - if (this.options.scaling.label.enabled === true) { - var fontDiff = this.options.scaling.label.max - this.options.scaling.label.min; - this.options.font.size = this.options.scaling.label.min + scale * fontDiff; - } - this.options.size = this.options.scaling.min + scale * sizeDiff; - } - }, - writable: true, - configurable: true - }, - draw: { + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - /** - * Draw this node in the given canvas - * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); - * @param {CanvasRenderingContext2D} ctx - */ - value: function draw(ctx) { - this.shape.draw(ctx, this.x, this.y, this.selected, this.hover); - }, - writable: true, - configurable: true - }, - resize: { + var _inherits = function (subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + + Object.defineProperty(exports, '__esModule', { + value: true + }); + var _BezierEdgeBase2 = __webpack_require__(88); - /** - * 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 - */ - value: function resize(ctx) { - this.shape.resize(ctx); - }, - writable: true, - configurable: true - }, - isOverlappingWith: { + var _BezierEdgeBase3 = _interopRequireWildcard(_BezierEdgeBase2); + var BezierEdgeDynamic = (function (_BezierEdgeBase) { + function BezierEdgeDynamic(options, body, labelModule) { + _classCallCheck(this, BezierEdgeDynamic); - /** - * 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 - */ - value: function isOverlappingWith(obj) { - return this.shape.left < obj.right && this.shape.left + this.shape.width > obj.left && this.shape.top < obj.bottom && this.shape.top + this.shape.height > obj.top; - }, - writable: true, - configurable: true + //this.via = undefined; // Here for completeness but not allowed to defined before super() is invoked. + _get(Object.getPrototypeOf(BezierEdgeDynamic.prototype), 'constructor', this).call(this, options, body, labelModule); // --> this calls the setOptions below + } + + _inherits(BezierEdgeDynamic, _BezierEdgeBase); + + _createClass(BezierEdgeDynamic, [{ + key: 'setOptions', + value: function setOptions(options) { + this.options = options; + this.from = this.body.nodes[this.options.from]; + this.to = this.body.nodes[this.options.to]; + this.id = this.options.id; + this.setupSupportNode(); } - }); + }, { + key: 'cleanup', + value: function cleanup() { + if (this.via !== undefined) { + delete this.body.nodes[this.via.id]; + this.via = undefined; + return true; + } + return false; + } + }, { + key: 'setupSupportNode', - return Node; - })(); + /** + * 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. + * + * The changed data is not called, if needed, it is returned by the main edge constructor. + * @private + */ + value: function setupSupportNode() { + if (this.via === undefined) { + var nodeId = 'edgeId:' + this.id; + var node = this.body.functions.createNode({ + id: nodeId, + mass: 1, + shape: 'circle', + image: '', + physics: true, + hidden: true + }); + this.body.nodes[nodeId] = node; + this.via = node; + this.via.parentEdgeId = this.id; + this.positionBezierNode(); + } + } + }, { + key: 'positionBezierNode', + value: function positionBezierNode() { + if (this.via !== undefined && this.from !== undefined && this.to !== undefined) { + 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 !== undefined) { + this.via.x = 0; + this.via.y = 0; + } + } + }, { + key: '_line', + + /** + * Draw a line between two nodes + * @param {CanvasRenderingContext2D} ctx + * @private + */ + value: function _line(ctx) { + // draw a straight line + ctx.beginPath(); + ctx.moveTo(this.from.x, this.from.y); + ctx.quadraticCurveTo(this.via.x, this.via.y, this.to.x, this.to.y); + ctx.stroke(); + return this.via; + } + }, { + key: 'getPoint', + + /** + * Combined function of pointOnLine and pointOnBezier. This gives the coordinates of a point on the line at a certain percentage of the way + * @param percentage + * @param via + * @returns {{x: number, y: number}} + * @private + */ + value: function getPoint(percentage) { + var t = percentage; + var x = Math.pow(1 - t, 2) * this.from.x + 2 * t * (1 - t) * this.via.x + Math.pow(t, 2) * this.to.x; + var y = Math.pow(1 - t, 2) * this.from.y + 2 * t * (1 - t) * this.via.y + Math.pow(t, 2) * this.to.y; + + return { x: x, y: y }; + } + }, { + key: '_findBorderPosition', + value: function _findBorderPosition(nearNode, ctx) { + return this._findBorderPositionBezier(nearNode, ctx, this.via); + } + }, { + key: '_getDistanceToEdge', + value: function _getDistanceToEdge(x1, y1, x2, y2, x3, y3) { + // x3,y3 is the point + return this._getDistanceToBezierEdge(x1, y1, x2, y2, x3, y3, this.via); + } + }]); - module.exports = Node; + return BezierEdgeDynamic; + })(_BezierEdgeBase3['default']); + + exports['default'] = BezierEdgeDynamic; + module.exports = exports['default']; /***/ }, -/* 81 */ +/* 86 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; - var _slicedToArray = function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { var _arr = []; for (var _iterator = arr[Symbol.iterator](), _step; !(_step = _iterator.next()).done;) { _arr.push(_step.value); if (i && _arr.length === i) break; } return _arr; } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); - var util = __webpack_require__(1); + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - var Label = (function () { - function Label(body, options) { - _classCallCheck(this, Label); + var _inherits = function (subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; - this.body = body; + Object.defineProperty(exports, '__esModule', { + value: true + }); - this.fontOptions = {}; - this.defaultOptions = { - color: "#343434", - size: 14, // px - face: "arial", - background: "none", - stroke: 0, // px - strokeColor: "white", - align: "horizontal" - }; - util.extend(this.fontOptions, this.defaultOptions); + var _BezierEdgeBase2 = __webpack_require__(88); - this.setOptions(options); - this.size = { top: 0, left: 0, width: 0, height: 0, yLine: 0 }; // could be cached + var _BezierEdgeBase3 = _interopRequireWildcard(_BezierEdgeBase2); + + var BezierEdgeStatic = (function (_BezierEdgeBase) { + function BezierEdgeStatic(options, body, labelModule) { + _classCallCheck(this, BezierEdgeStatic); + + _get(Object.getPrototypeOf(BezierEdgeStatic.prototype), 'constructor', this).call(this, options, body, labelModule); } - _prototypeProperties(Label, null, { - setOptions: { - value: function setOptions(options) { - this.options = options; - if (options.label !== undefined) { - this.labelDirty = true; - } - if (options.font) { - if (typeof options.font === "string") { - var optionsArray = options.font.split(" "); - this.fontOptions.size = optionsArray[0].replace("px", ""); - this.fontOptions.face = optionsArray[1]; - this.fontOptions.color = optionsArray[2]; - } else if (typeof options.font === "object") { - this.fontOptions = util.bridgeObject(options.font); + _inherits(BezierEdgeStatic, _BezierEdgeBase); + + _createClass(BezierEdgeStatic, [{ + key: 'cleanup', + value: function cleanup() { + return false; + } + }, { + key: '_line', + + /** + * Draw a line between two nodes + * @param {CanvasRenderingContext2D} ctx + * @private + */ + value: function _line(ctx) { + // draw a straight line + ctx.beginPath(); + ctx.moveTo(this.from.x, this.from.y); + var via = this._getViaCoordinates(); + + // fallback to normal straight edges + if (via.x === undefined) { + ctx.lineTo(this.to.x, this.to.y); + ctx.stroke(); + return undefined; + } else { + ctx.quadraticCurveTo(via.x, via.y, this.to.x, this.to.y); + ctx.stroke(); + return via; + } + } + }, { + key: '_getViaCoordinates', + value: function _getViaCoordinates() { + var xVia = undefined; + var yVia = undefined; + var factor = this.options.smooth.roundness; + var type = this.options.smooth.type; + var dx = Math.abs(this.from.x - this.to.x); + var dy = Math.abs(this.from.y - this.to.y); + if (type === 'discrete' || type === 'diagonalCross') { + if (Math.abs(this.from.x - this.to.x) < Math.abs(this.from.y - this.to.y)) { + if (this.from.y > this.to.y) { + if (this.from.x < this.to.x) { + xVia = this.from.x + factor * dy; + yVia = this.from.y - factor * dy; + } else if (this.from.x > this.to.x) { + xVia = this.from.x - factor * dy; + yVia = this.from.y - factor * dy; + } + } else if (this.from.y < this.to.y) { + if (this.from.x < this.to.x) { + xVia = this.from.x + factor * dy; + yVia = this.from.y + factor * dy; + } else if (this.from.x > this.to.x) { + xVia = this.from.x - factor * dy; + yVia = this.from.y + factor * dy; + } + } + if (type === 'discrete') { + xVia = dx < factor * dy ? this.from.x : xVia; + } + } else if (Math.abs(this.from.x - this.to.x) > Math.abs(this.from.y - this.to.y)) { + if (this.from.y > this.to.y) { + if (this.from.x < this.to.x) { + xVia = this.from.x + factor * dx; + yVia = this.from.y - factor * dx; + } else if (this.from.x > this.to.x) { + xVia = this.from.x - factor * dx; + yVia = this.from.y - factor * dx; + } + } else if (this.from.y < this.to.y) { + if (this.from.x < this.to.x) { + xVia = this.from.x + factor * dx; + yVia = this.from.y + factor * dx; + } else if (this.from.x > this.to.x) { + xVia = this.from.x - factor * dx; + yVia = this.from.y + factor * dx; + } + } + if (type === 'discrete') { + yVia = dy < factor * dx ? this.from.y : yVia; } - this.fontOptions.size = Number(this.fontOptions.size); } - }, - writable: true, - configurable: true - }, - draw: { - + } else if (type === 'straightCross') { + if (Math.abs(this.from.x - this.to.x) < Math.abs(this.from.y - this.to.y)) { + // up - down + xVia = this.from.x; + if (this.from.y < this.to.y) { + yVia = this.to.y - (1 - factor) * dy; + } else { + yVia = this.to.y + (1 - factor) * dy; + } + } else if (Math.abs(this.from.x - this.to.x) > Math.abs(this.from.y - this.to.y)) { + // left - right + if (this.from.x < this.to.x) { + xVia = this.to.x - (1 - factor) * dx; + } else { + xVia = this.to.x + (1 - factor) * dx; + } + yVia = this.from.y; + } + } else if (type === 'horizontal') { + if (this.from.x < this.to.x) { + xVia = this.to.x - (1 - factor) * dx; + } else { + xVia = this.to.x + (1 - factor) * dx; + } + yVia = this.from.y; + } else if (type === 'vertical') { + xVia = this.from.x; + if (this.from.y < this.to.y) { + yVia = this.to.y - (1 - factor) * dy; + } else { + yVia = this.to.y + (1 - factor) * dy; + } + } else if (type === 'curvedCW') { + dx = this.to.x - this.from.x; + dy = this.from.y - this.to.y; + var radius = Math.sqrt(dx * dx + dy * dy); + var pi = Math.PI; + + var originalAngle = Math.atan2(dy, dx); + var myAngle = (originalAngle + (factor * 0.5 + 0.5) * pi) % (2 * pi); + + xVia = this.from.x + (factor * 0.5 + 0.5) * radius * Math.sin(myAngle); + yVia = this.from.y + (factor * 0.5 + 0.5) * radius * Math.cos(myAngle); + } else if (type === 'curvedCCW') { + dx = this.to.x - this.from.x; + dy = this.from.y - this.to.y; + var radius = Math.sqrt(dx * dx + dy * dy); + var pi = Math.PI; + + var originalAngle = Math.atan2(dy, dx); + var myAngle = (originalAngle + (-factor * 0.5 + 0.5) * pi) % (2 * pi); + + xVia = this.from.x + (factor * 0.5 + 0.5) * radius * Math.sin(myAngle); + yVia = this.from.y + (factor * 0.5 + 0.5) * radius * Math.cos(myAngle); + } else { + // continuous + if (Math.abs(this.from.x - this.to.x) < Math.abs(this.from.y - this.to.y)) { + if (this.from.y > this.to.y) { + if (this.from.x < this.to.x) { + xVia = this.from.x + factor * dy; + yVia = this.from.y - factor * dy; + xVia = this.to.x < xVia ? this.to.x : xVia; + } else if (this.from.x > this.to.x) { + xVia = this.from.x - factor * dy; + yVia = this.from.y - factor * dy; + xVia = this.to.x > xVia ? this.to.x : xVia; + } + } else if (this.from.y < this.to.y) { + if (this.from.x < this.to.x) { + xVia = this.from.x + factor * dy; + yVia = this.from.y + factor * dy; + xVia = this.to.x < xVia ? this.to.x : xVia; + } else if (this.from.x > this.to.x) { + xVia = this.from.x - factor * dy; + yVia = this.from.y + factor * dy; + xVia = this.to.x > xVia ? this.to.x : xVia; + } + } + } else if (Math.abs(this.from.x - this.to.x) > Math.abs(this.from.y - this.to.y)) { + if (this.from.y > this.to.y) { + if (this.from.x < this.to.x) { + xVia = this.from.x + factor * dx; + yVia = this.from.y - factor * dx; + yVia = this.to.y > yVia ? this.to.y : yVia; + } else if (this.from.x > this.to.x) { + xVia = this.from.x - factor * dx; + yVia = this.from.y - factor * dx; + yVia = this.to.y > yVia ? this.to.y : yVia; + } + } else if (this.from.y < this.to.y) { + if (this.from.x < this.to.x) { + xVia = this.from.x + factor * dx; + yVia = this.from.y + factor * dx; + yVia = this.to.y < yVia ? this.to.y : yVia; + } else if (this.from.x > this.to.x) { + xVia = this.from.x - factor * dx; + yVia = this.from.y + factor * dx; + yVia = this.to.y < yVia ? this.to.y : yVia; + } + } + } + } + return { x: xVia, y: yVia }; + } + }, { + key: '_findBorderPosition', + value: function _findBorderPosition(nearNode, ctx) { + var options = arguments[2] === undefined ? {} : arguments[2]; - /** - * Main function. This is called from anything that wants to draw a label. - * @param ctx - * @param x - * @param y - * @param selected - * @param baseline - */ - value: function draw(ctx, x, y, selected) { - var baseline = arguments[4] === undefined ? "middle" : arguments[4]; - // if no label, return - if (this.options.label === undefined) { - return; - } // check if we have to render the label - var viewFontSize = this.fontOptions.size * this.body.view.scale; - if (this.options.label && viewFontSize < this.options.scaling.label.drawThreshold - 1) { - return; - } // update the size cache if required - this.calculateLabelSize(ctx, selected, x, y, baseline); + return this._findBorderPositionBezier(nearNode, ctx, options.via); + } + }, { + key: '_getDistanceToEdge', + value: function _getDistanceToEdge(x1, y1, x2, y2, x3, y3) { + var via = arguments[6] === undefined ? this._getViaCoordinates() : arguments[6]; + // x3,y3 is the point + return this._getDistanceToBezierEdge(x1, y1, x2, y2, x3, y3, via); + } + }, { + key: 'getPoint', - // create the fontfill background - this._drawBackground(ctx); - // draw text - this._drawText(ctx, selected, x, y, baseline); - }, - writable: true, - configurable: true - }, - _drawBackground: { + /** + * Combined function of pointOnLine and pointOnBezier. This gives the coordinates of a point on the line at a certain percentage of the way + * @param percentage + * @param via + * @returns {{x: number, y: number}} + * @private + */ + value: function getPoint(percentage) { + var via = arguments[1] === undefined ? this._getViaCoordinates() : arguments[1]; - /** - * Draws the label background - * @param {CanvasRenderingContext2D} ctx - * @private - */ - value: function _drawBackground(ctx) { - if (this.fontOptions.background !== undefined && this.fontOptions.background !== "none") { - ctx.fillStyle = this.fontOptions.background; + var t = percentage; + var x = Math.pow(1 - t, 2) * this.from.x + 2 * t * (1 - t) * via.x + Math.pow(t, 2) * this.to.x; + var y = Math.pow(1 - t, 2) * this.from.y + 2 * t * (1 - t) * via.y + Math.pow(t, 2) * this.to.y; - var lineMargin = 2; + return { x: x, y: y }; + } + }]); - switch (this.fontOptions.align) { - case "middle": - ctx.fillRect(-this.size.width * 0.5, -this.size.height * 0.5, this.size.width, this.size.height); - break; - case "top": - ctx.fillRect(-this.size.width * 0.5, -(this.size.height + lineMargin), this.size.width, this.size.height); - break; - case "bottom": - ctx.fillRect(-this.size.width * 0.5, lineMargin, this.size.width, this.size.height); - break; - default: - ctx.fillRect(this.size.left, this.size.top, this.size.width, this.size.height); - break; - } - } - }, - writable: true, - configurable: true - }, - _drawText: { + return BezierEdgeStatic; + })(_BezierEdgeBase3['default']); + exports['default'] = BezierEdgeStatic; + module.exports = exports['default']; - /** - * - * @param ctx - * @param x - * @param baseline - * @private - */ - value: function _drawText(ctx, selected, x, y) { - var baseline = arguments[4] === undefined ? "middle" : arguments[4]; - var fontSize = this.fontOptions.size; - var viewFontSize = fontSize * this.body.view.scale; - // 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 (viewFontSize >= this.options.scaling.label.maxVisible) { - fontSize = Number(this.options.scaling.label.maxVisible) / this.body.view.scale; - } +/***/ }, +/* 87 */ +/***/ function(module, exports, __webpack_require__) { - var yLine = this.size.yLine; - var _getColor = this._getColor(viewFontSize); + 'use strict'; - var _getColor2 = _slicedToArray(_getColor, 2); + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; - var fontColor = _getColor2[0]; - var strokeColor = _getColor2[1]; - var _ref = this._setAlignment(ctx, x, yLine, baseline); + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; - var _ref2 = _slicedToArray(_ref, 2); + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); - x = _ref2[0]; - yLine = _ref2[1]; + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + var _inherits = function (subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; - // configure context for drawing the text - ctx.font = (selected ? "bold " : "") + fontSize + "px " + this.fontOptions.face; - ctx.fillStyle = fontColor; - ctx.textAlign = "center"; + Object.defineProperty(exports, '__esModule', { + value: true + }); - // set the strokeWidth - if (this.fontOptions.stroke > 0) { - ctx.lineWidth = this.fontOptions.stroke; - ctx.strokeStyle = strokeColor; - ctx.lineJoin = "round"; - } + var _EdgeBase2 = __webpack_require__(89); - // draw the text - for (var i = 0; i < this.lineCount; i++) { - if (this.fontOptions.stroke > 0) { - ctx.strokeText(this.lines[i], x, yLine); - } - ctx.fillText(this.lines[i], x, yLine); - yLine += fontSize; - } - }, - writable: true, - configurable: true - }, - _setAlignment: { - value: function _setAlignment(ctx, x, yLine, baseline) { - // check for label alignment (for edges) - // TODO: make alignment for nodes - if (this.fontOptions.align !== "horizontal") { - x = 0; - yLine = 0; - - var lineMargin = 2; - if (this.fontOptions.align === "top") { - ctx.textBaseline = "alphabetic"; - yLine -= 2 * lineMargin; // distance from edge, required because we use alphabetic. Alphabetic has less difference between browsers - } else if (this.fontOptions.align === "bottom") { - ctx.textBaseline = "hanging"; - yLine += 2 * lineMargin; // distance from edge, required because we use hanging. Hanging has less difference between browsers - } else { - ctx.textBaseline = "middle"; - } - } else { - ctx.textBaseline = baseline; - } + var _EdgeBase3 = _interopRequireWildcard(_EdgeBase2); - return [x, yLine]; - }, - writable: true, - configurable: true - }, - _getColor: { + var StraightEdge = (function (_EdgeBase) { + function StraightEdge(options, body, labelModule) { + _classCallCheck(this, StraightEdge); - /** - * fade in when relative scale is between threshold and threshold - 1. - * If the relative scale would be smaller than threshold -1 the draw function would have returned before coming here. - * - * @param viewFontSize - * @returns {*[]} - * @private - */ - value: function _getColor(viewFontSize) { - var fontColor = this.fontOptions.color || "#000000"; - var strokeColor = this.fontOptions.strokeColor || "#ffffff"; - if (viewFontSize <= this.options.scaling.label.drawThreshold) { - var opacity = Math.max(0, Math.min(1, 1 - (this.options.scaling.label.drawThreshold - viewFontSize))); - fontColor = util.overrideOpacity(fontColor, opacity); - strokeColor = util.overrideOpacity(strokeColor, opacity); - } - return [fontColor, strokeColor]; - }, - writable: true, - configurable: true - }, - getTextSize: { + _get(Object.getPrototypeOf(StraightEdge.prototype), 'constructor', this).call(this, options, body, labelModule); + } + _inherits(StraightEdge, _EdgeBase); - /** - * - * @param ctx - * @param selected - * @returns {{width: number, height: number}} - */ - value: function getTextSize(ctx) { - var selected = arguments[1] === undefined ? false : arguments[1]; - var size = { - width: this._processLabel(ctx, selected), - height: this.fontOptions.size * this.lineCount, - lineCount: this.lineCount - }; - return size; - }, - writable: true, - configurable: true - }, - calculateLabelSize: { + _createClass(StraightEdge, [{ + key: 'cleanup', + value: function cleanup() { + return false; + } + }, { + key: '_line', + /** + * Draw a line between two nodes + * @param {CanvasRenderingContext2D} ctx + * @private + */ + value: function _line(ctx) { + // draw a straight line + ctx.beginPath(); + ctx.moveTo(this.from.x, this.from.y); + ctx.lineTo(this.to.x, this.to.y); + ctx.stroke(); + return undefined; + } + }, { + key: 'getPoint', - /** - * - * @param ctx - * @param selected - * @param x - * @param y - * @param baseline - */ - value: function calculateLabelSize(ctx, selected) { - var x = arguments[2] === undefined ? 0 : arguments[2]; - var y = arguments[3] === undefined ? 0 : arguments[3]; - var baseline = arguments[4] === undefined ? "middle" : arguments[4]; - if (this.labelDirty === true) { - this.size.width = this._processLabel(ctx, selected); - } - this.size.height = this.fontOptions.size * this.lineCount; - this.size.left = x - this.size.width * 0.5; - this.size.top = y - this.size.height * 0.5; - this.size.yLine = y + (1 - this.lineCount) * 0.5 * this.fontOptions.size; - if (baseline === "hanging") { - this.size.top += 0.5 * this.fontOptions.size; - this.size.top += 4; // distance from node, required because we use hanging. Hanging has less difference between browsers - this.size.yLine += 4; // distance from node - } - - this.labelDirty = false; - }, - writable: true, - configurable: true - }, - _processLabel: { + /** + * Combined function of pointOnLine and pointOnBezier. This gives the coordinates of a point on the line at a certain percentage of the way + * @param percentage + * @param via + * @returns {{x: number, y: number}} + * @private + */ + value: function getPoint(percentage) { + return { + x: (1 - percentage) * this.from.x + percentage * this.to.x, + y: (1 - percentage) * this.from.y + percentage * this.to.y + }; + } + }, { + key: '_findBorderPosition', + value: function _findBorderPosition(nearNode, ctx) { + var node1 = this.to; + var node2 = this.from; + if (nearNode.id === this.from.id) { + node1 = this.from; + node2 = this.to; + } + var angle = Math.atan2(node1.y - node2.y, node1.x - node2.x); + var dx = node1.x - node2.x; + var dy = node1.y - node2.y; + var edgeSegmentLength = Math.sqrt(dx * dx + dy * dy); + var toBorderDist = nearNode.distanceToBorder(ctx, angle); + var toBorderPoint = (edgeSegmentLength - toBorderDist) / edgeSegmentLength; - /** - * This calculates the width as well as explodes the label string and calculates the amount of lines. - * @param ctx - * @param selected - * @returns {number} - * @private - */ - value: function _processLabel(ctx, selected) { - var width = 0; - var lines = [""]; - var lineCount = 0; - if (this.options.label !== undefined) { - lines = String(this.options.label).split("\n"); - lineCount = lines.length; - ctx.font = (selected ? "bold " : "") + this.fontOptions.size + "px " + this.fontOptions.face; - width = ctx.measureText(lines[0]).width; - for (var i = 1; i < lineCount; i++) { - var lineWidth = ctx.measureText(lines[i]).width; - width = lineWidth > width ? lineWidth : width; - } - } - this.lines = lines; - this.lineCount = lineCount; + var borderPos = {}; + borderPos.x = (1 - toBorderPoint) * node2.x + toBorderPoint * node1.x; + borderPos.y = (1 - toBorderPoint) * node2.y + toBorderPoint * node1.y; - return width; - }, - writable: true, - configurable: true + return borderPos; } - }); + }, { + key: '_getDistanceToEdge', + value: function _getDistanceToEdge(x1, y1, x2, y2, x3, y3) { + // x3,y3 is the point + return this._getDistanceToLine(x1, y1, x2, y2, x3, y3); + } + }]); - return Label; - })(); + return StraightEdge; + })(_EdgeBase3['default']); - module.exports = Label; + exports['default'] = StraightEdge; + module.exports = exports['default']; /***/ }, -/* 82 */ +/* 88 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; - var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; - var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); - var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var _inherits = function (subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; - var NodeBase = _interopRequire(__webpack_require__(97)); + Object.defineProperty(exports, '__esModule', { + value: true + }); - var Box = (function (NodeBase) { - function Box(options, body, labelModule) { - _classCallCheck(this, Box); + var _EdgeBase2 = __webpack_require__(89); + + var _EdgeBase3 = _interopRequireWildcard(_EdgeBase2); - _get(Object.getPrototypeOf(Box.prototype), "constructor", this).call(this, options, body, labelModule); + var BezierEdgeBase = (function (_EdgeBase) { + function BezierEdgeBase(options, body, labelModule) { + _classCallCheck(this, BezierEdgeBase); + + _get(Object.getPrototypeOf(BezierEdgeBase.prototype), 'constructor', this).call(this, options, body, labelModule); } - _inherits(Box, NodeBase); + _inherits(BezierEdgeBase, _EdgeBase); - _prototypeProperties(Box, null, { - resize: { - value: function resize(ctx) { - if (this.width === undefined) { - var margin = 5; - var textSize = this.labelModule.getTextSize(ctx, this.selected); - this.width = textSize.width + 2 * margin; - this.height = textSize.height + 2 * margin; - } - }, - writable: true, - configurable: true - }, - draw: { - value: function draw(ctx, x, y, selected, hover) { - this.resize(ctx); - this.left = x - this.width / 2; - this.top = y - this.height / 2; + _createClass(BezierEdgeBase, [{ + key: '_findBorderPositionBezier', - var borderWidth = this.options.borderWidth; - var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; + /** + * This function uses binary search to look for the point where the bezier curve crosses the border of the node. + * + * @param nearNode + * @param ctx + * @param viaNode + * @param nearNode + * @param ctx + * @param viaNode + * @param nearNode + * @param ctx + * @param viaNode + */ + value: function _findBorderPositionBezier(nearNode, ctx) { + var viaNode = arguments[2] === undefined ? this._getViaCoordinates() : arguments[2]; + + var maxIterations = 10; + var iteration = 0; + var low = 0; + var high = 1; + var pos, angle, distanceToBorder, distanceToPoint, difference; + var threshold = 0.2; + var node = this.to; + var from = false; + if (nearNode.id === this.from.id) { + node = this.from; + from = true; + } - ctx.strokeStyle = selected ? this.options.color.highlight.border : hover ? this.options.color.hover.border : this.options.color.border; - ctx.lineWidth = selected ? selectionLineWidth : borderWidth; - ctx.lineWidth /= this.body.view.scale; - ctx.lineWidth = Math.min(this.width, ctx.lineWidth); + while (low <= high && iteration < maxIterations) { + var middle = (low + high) * 0.5; + + pos = this.getPoint(middle, viaNode); + angle = Math.atan2(node.y - pos.y, node.x - pos.x); + distanceToBorder = node.distanceToBorder(ctx, angle); + distanceToPoint = Math.sqrt(Math.pow(pos.x - node.x, 2) + Math.pow(pos.y - node.y, 2)); + difference = distanceToBorder - distanceToPoint; + 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; + } + } - ctx.fillStyle = selected ? this.options.color.highlight.background : hover ? this.options.color.hover.background : this.options.color.background; + iteration++; + } + pos.t = middle; - ctx.roundRect(this.left, this.top, this.width, this.height, this.options.size); - ctx.fill(); - ctx.stroke(); + return pos; + } + }, { + key: '_getDistanceToBezierEdge', - this.boundingBox.top = this.top; - this.boundingBox.left = this.left; - this.boundingBox.right = this.left + this.width; - this.boundingBox.bottom = this.top + this.height; + /** + * 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 + */ + value: function _getDistanceToBezierEdge(x1, y1, x2, y2, x3, y3, via) { + // x3,y3 is the point + var xVia = undefined, + yVia = undefined; + xVia = via.x; + yVia = via.y; + var minDistance = 1000000000; + var distance = undefined; + var i = undefined, + t = undefined, + x = undefined, + y = undefined; + var lastX = x1; + var lastY = y1; + for (i = 1; 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; + } - this.labelModule.draw(ctx, x, y, selected); - }, - writable: true, - configurable: true - }, - distanceToBorder: { - value: function distanceToBorder(ctx, angle) { - this.resize(ctx); - 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); - }, - writable: true, - configurable: true + return minDistance; } - }); + }]); - return Box; - })(NodeBase); + return BezierEdgeBase; + })(_EdgeBase3['default']); - module.exports = Box; + exports['default'] = BezierEdgeBase; + module.exports = exports['default']; /***/ }, -/* 83 */ +/* 89 */ /***/ function(module, exports, __webpack_require__) { "use strict"; - var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; + var _slicedToArray = function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; - var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); - var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + Object.defineProperty(exports, "__esModule", { + value: true + }); + var util = __webpack_require__(1); - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var EdgeBase = (function () { + function EdgeBase(options, body, labelModule) { + _classCallCheck(this, EdgeBase); - var CircleImageBase = _interopRequire(__webpack_require__(98)); + this.body = body; + this.labelModule = labelModule; + this.setOptions(options); + this.colorDirty = true; + this.color = {}; + } - var Circle = (function (CircleImageBase) { - function Circle(options, body, labelModule) { - _classCallCheck(this, Circle); + _createClass(EdgeBase, [{ + key: "setOptions", + value: function setOptions(options) { + this.options = options; + this.from = this.body.nodes[this.options.from]; + this.to = this.body.nodes[this.options.to]; + this.id = this.options.id; + } + }, { + key: "drawLine", - _get(Object.getPrototypeOf(Circle.prototype), "constructor", this).call(this, options, body, labelModule); - } + /** + * 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 + */ + value: function drawLine(ctx, selected, hover) { + // set style + ctx.strokeStyle = this.getColor(ctx); + ctx.lineWidth = this.getLineWidth(selected, hover); + var via = undefined; + if (this.from != this.to) { + // draw line + if (this.options.dashes.enabled === true) { + via = this._drawDashedLine(ctx); + } else { + via = this._line(ctx); + } + } else { + var _getCircleData = this._getCircleData(ctx); - _inherits(Circle, CircleImageBase); + var _getCircleData2 = _slicedToArray(_getCircleData, 3); - _prototypeProperties(Circle, null, { - resize: { - value: function resize(ctx, selected) { - if (this.width === undefined) { - var margin = 5; - var textSize = this.labelModule.getTextSize(ctx, selected); - var diameter = Math.max(textSize.width, textSize.height) + 2 * margin; - this.options.size = diameter / 2; + var x = _getCircleData2[0]; + var y = _getCircleData2[1]; + var radius = _getCircleData2[2]; - this.width = diameter; - this.height = diameter; + this._circle(ctx, x, y, radius); + } + + return via; + } + }, { + key: "_drawDashedLine", + value: function _drawDashedLine(ctx) { + var via = undefined; + // only firefox and chrome support this method, else we use the legacy one. + if (ctx.setLineDash !== undefined && this.options.dashes.altLength === undefined) { + ctx.save(); + // configure the dash pattern + var pattern = [0]; + if (this.options.dashes.length !== undefined && this.options.dashes.gap !== undefined) { + pattern = [this.options.dashes.length, this.options.dashes.gap]; + } else { + pattern = [5, 5]; } - }, - writable: true, - configurable: true - }, - draw: { - value: function draw(ctx, x, y, selected, hover) { - this.resize(ctx, selected); - this.left = x - this.width / 2; - this.top = y - this.height / 2; - this._drawRawCircle(ctx, x, y, selected, hover, this.options.size); + // set dash settings for chrome or firefox + ctx.setLineDash(pattern); + ctx.lineDashOffset = 0; - this.boundingBox.top = y - this.options.size; - this.boundingBox.left = x - this.options.size; - this.boundingBox.right = x + this.options.size; - this.boundingBox.bottom = y + this.options.size; + // draw the line + via = this._line(ctx); - this.labelModule.draw(ctx, x, y, selected); - }, - writable: true, - configurable: true - }, - distanceToBorder: { - value: function distanceToBorder(ctx, angle) { - this.resize(ctx); - 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); - }, - writable: true, - configurable: true + // restore the dash settings. + ctx.setLineDash([0]); + ctx.lineDashOffset = 0; + ctx.restore(); + } else { + // unsupporting smooth lines + // draw dashes line + ctx.beginPath(); + ctx.lineCap = "round"; + if (this.options.dashes.altLength !== undefined) //If an alt dash value has been set add to the array this value + { + ctx.dashesLine(this.from.x, this.from.y, this.to.x, this.to.y, [this.options.dashes.length, this.options.dashes.gap, this.options.dashes.altLength, this.options.dashes.gap]); + } else if (this.options.dashes.length !== undefined && this.options.dashes.gap !== undefined) //If a dash and gap value has been set add to the array this value + { + ctx.dashesLine(this.from.x, this.from.y, this.to.x, this.to.y, [this.options.dashes.length, this.options.dashes.gap]); + } else //If all else fails draw a line + { + ctx.moveTo(this.from.x, this.from.y); + ctx.lineTo(this.to.x, this.to.y); + } + ctx.stroke(); + } + return via; } - }); + }, { + key: "findBorderPosition", + value: function findBorderPosition(nearNode, ctx, options) { + if (this.from != this.to) { + return this._findBorderPosition(nearNode, ctx, options); + } else { + return this._findBorderPositionCircle(nearNode, ctx, options); + } + } + }, { + key: "findBorderPositions", + value: function findBorderPositions(ctx) { + var from = {}; + var to = {}; + if (this.from != this.to) { + from = this._findBorderPosition(this.from, ctx); + to = this._findBorderPosition(this.to, ctx); + } else { + var _getCircleData3 = this._getCircleData(ctx); - return Circle; - })(CircleImageBase); + var _getCircleData32 = _slicedToArray(_getCircleData3, 3); - module.exports = Circle; + var x = _getCircleData32[0]; + var y = _getCircleData32[1]; + var radius = _getCircleData32[2]; -/***/ }, -/* 84 */ -/***/ function(module, exports, __webpack_require__) { + from = this._findBorderPositionCircle(this.from, ctx, { x: x, y: y, low: 0.25, high: 0.6, direction: -1 }); + to = this._findBorderPositionCircle(this.from, ctx, { x: x, y: y, low: 0.6, high: 0.8, direction: 1 }); + } + return { from: from, to: to }; + } + }, { + key: "_getCircleData", + value: function _getCircleData(ctx) { + var x = undefined, + y = undefined; + var node = this.from; + var radius = this.options.selfReferenceSize; - "use strict"; + if (ctx !== undefined) { + if (node.shape.width === undefined) { + node.shape.resize(ctx); + } + } + + // get circle coordinates + if (node.shape.width > node.shape.height) { + x = node.x + node.shape.width * 0.5; + y = node.y - radius; + } else { + x = node.x + radius; + y = node.y - node.shape.height * 0.5; + } + return [x, y, radius]; + } + }, { + key: "_pointOnCircle", + /** + * 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 + */ + value: function _pointOnCircle(x, y, radius, percentage) { + var angle = percentage * 2 * Math.PI; + return { + x: x + radius * Math.cos(angle), + y: y - radius * Math.sin(angle) + }; + } + }, { + key: "_findBorderPositionCircle", - var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; + /** + * This function uses binary search to look for the point where the circle crosses the border of the node. + * @param node + * @param ctx + * @param options + * @returns {*} + * @private + */ + value: function _findBorderPositionCircle(node, ctx, options) { + var x = options.x; + var y = options.y; + var low = options.low; + var high = options.high; + var direction = options.direction; + + var maxIterations = 10; + var iteration = 0; + var radius = this.options.selfReferenceSize; + var pos = undefined, + angle = undefined, + distanceToBorder = undefined, + distanceToPoint = undefined, + difference = undefined; + var threshold = 0.05; + var middle = (low + high) * 0.5; + + while (low <= high && iteration < maxIterations) { + middle = (low + high) * 0.5; + + pos = this._pointOnCircle(x, y, radius, middle); + angle = Math.atan2(node.y - pos.y, node.x - pos.x); + distanceToBorder = node.distanceToBorder(ctx, angle); + distanceToPoint = Math.sqrt(Math.pow(pos.x - node.x, 2) + Math.pow(pos.y - node.y, 2)); + difference = distanceToBorder - distanceToPoint; + if (Math.abs(difference) < threshold) { + break; // found + } else if (difference > 0) { + // distance to nodes is larger than distance to border --> t needs to be bigger if we're looking at the to node. + if (direction > 0) { + low = middle; + } else { + high = middle; + } + } else { + if (direction > 0) { + high = middle; + } else { + low = middle; + } + } + iteration++; + } + pos.t = middle; - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; + return pos; + } + }, { + key: "getLineWidth", - var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + /** + * Get the line width of the edge. Depends on width and whether one of the + * connected nodes is selected. + * @return {Number} width + * @private + */ + value: function getLineWidth(selected, hover) { + if (selected === true) { + return Math.max(Math.min(this.options.widthSelectionMultiplier * this.options.width, this.options.scaling.max), 0.3 / this.body.view.scale); + } else { + if (hover === true) { + return Math.max(Math.min(this.options.hoverWidth, this.options.scaling.max), 0.3 / this.body.view.scale); + } else { + return Math.max(this.options.width, 0.3 / this.body.view.scale); + } + } + } + }, { + key: "getColor", + value: function getColor(ctx) { + var colorOptions = this.options.color; + + if (colorOptions.inherit.enabled === true) { + if (colorOptions.inherit.useGradients === true) { + var grd = ctx.createLinearGradient(this.from.x, this.from.y, this.to.x, this.to.y); + var fromColor = undefined, + toColor = undefined; + fromColor = this.from.options.color.highlight.border; + toColor = this.to.options.color.highlight.border; + + if (this.from.selected === false && this.to.selected === false) { + fromColor = util.overrideOpacity(this.from.options.color.border, this.options.color.opacity); + toColor = util.overrideOpacity(this.to.options.color.border, this.options.color.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); - var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + // -------------------- this returns -------------------- // + return grd; + } - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + if (this.colorDirty === true) { + if (colorOptions.inherit.source === "to") { + this.color.highlight = this.to.options.color.highlight.border; + this.color.hover = this.to.options.color.hover.border; + this.color.color = util.overrideOpacity(this.to.options.color.border, colorOptions.opacity); + } else { + // (this.options.color.inherit.source === "from") { + this.color.highlight = this.from.options.color.highlight.border; + this.color.hover = this.from.options.color.hover.border; + this.color.color = util.overrideOpacity(this.from.options.color.border, colorOptions.opacity); + } + } + } else if (this.colorDirty === true) { + this.color.highlight = colorOptions.highlight; + this.color.hover = colorOptions.hover; + this.color.color = util.overrideOpacity(colorOptions.color, colorOptions.opacity); + } - var CircleImageBase = _interopRequire(__webpack_require__(98)); + // if color inherit is on and gradients are used, the function has already returned by now. + this.colorDirty = false; - var CircularImage = (function (CircleImageBase) { - function CircularImage(options, body, labelModule, imageObj) { - _classCallCheck(this, CircularImage); + if (this.selected === true) { + return this.color.highlight; + } else if (this.hover === true) { + return this.color.hover; + } else { + return this.color.color; + } + } + }, { + key: "_circle", - _get(Object.getPrototypeOf(CircularImage.prototype), "constructor", this).call(this, options, body, labelModule); - this.imageObj = imageObj; - this._swapToImageResizeWhenImageLoaded = true; - } + /** + * Draw a line from a node to itself, a circle + * @param {CanvasRenderingContext2D} ctx + * @param {Number} x + * @param {Number} y + * @param {Number} radius + * @private + */ + value: function _circle(ctx, x, y, radius) { + // draw a circle + ctx.beginPath(); + ctx.arc(x, y, radius, 0, 2 * Math.PI, false); + ctx.stroke(); + } + }, { + key: "getDistanceToEdge", - _inherits(CircularImage, CircleImageBase); + /** + * 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 + */ + value: function getDistanceToEdge(x1, y1, x2, y2, x3, y3, via) { + // x3,y3 is the point + var returnValue = 0; + if (this.from != this.to) { + returnValue = this._getDistanceToEdge(x1, y1, x2, y2, x3, y3, via); + } else { + var _getCircleData4 = this._getCircleData(); - _prototypeProperties(CircularImage, null, { - resize: { - value: function resize() { - if (this.imageObj.src === undefined || this.imageObj.width === undefined || this.imageObj.height === undefined) { - if (!this.width) { - var diameter = this.options.size * 2; - this.width = diameter; - this.height = diameter; - this._swapToImageResizeWhenImageLoaded = true; - } - } else { - if (this._swapToImageResizeWhenImageLoaded) { - this.width = undefined; - this.height = undefined; - this._swapToImageResizeWhenImageLoaded = false; - } - this._resizeImage(); - } - }, - writable: true, - configurable: true - }, - draw: { - value: function draw(ctx, x, y, selected, hover) { - this.resize(); + var _getCircleData42 = _slicedToArray(_getCircleData4, 3); - this.left = x - this.width / 2; - this.top = y - this.height / 2; + var x = _getCircleData42[0]; + var y = _getCircleData42[1]; + var radius = _getCircleData42[2]; - var size = Math.min(0.5 * this.height, 0.5 * this.width); - this._drawRawCircle(ctx, x, y, selected, hover, size); + var dx = x - x3; + var dy = y - y3; + returnValue = Math.abs(Math.sqrt(dx * dx + dy * dy) - radius); + } - ctx.save(); - ctx.circle(x, y, size); + if (this.labelModule.size.left < x3 && this.labelModule.size.left + this.labelModule.size.width > x3 && this.labelModule.size.top < y3 && this.labelModule.size.top + this.labelModule.size.height > y3) { + return 0; + } else { + return returnValue; + } + } + }, { + key: "_getDistanceToLine", + value: function _getDistanceToLine(x1, y1, x2, y2, x3, y3) { + var px = x2 - x1; + var py = y2 - y1; + var something = px * px + py * py; + var u = ((x3 - x1) * px + (y3 - y1) * py) / something; + + if (u > 1) { + u = 1; + } else if (u < 0) { + u = 0; + } + + var x = x1 + u * px; + var y = y1 + u * py; + var dx = x - x3; + var dy = y - y3; + + //# Note: If the actual distance does not matter, + //# if you only want to compare what this function + //# returns to other results of this function, you + //# can just return the squared distance instead + //# (i.e. remove the sqrt) to gain a little performance + + return Math.sqrt(dx * dx + dy * dy); + } + }, { + key: "drawArrowHead", + + /** + * + * @param ctx + * @param position + * @param viaNode + */ + value: function drawArrowHead(ctx, position, viaNode, selected, hover) { + // set style + ctx.strokeStyle = this.getColor(ctx); + ctx.fillStyle = ctx.strokeStyle; + ctx.lineWidth = this.getLineWidth(selected, hover); + + // set lets + var angle = undefined; + var length = undefined; + var arrowPos = undefined; + var node1 = undefined; + var node2 = undefined; + var guideOffset = undefined; + var scaleFactor = undefined; + + if (position === "from") { + node1 = this.from; + node2 = this.to; + guideOffset = 0.1; + scaleFactor = this.options.arrows.from.scaleFactor; + } else if (position === "to") { + node1 = this.to; + node2 = this.from; + guideOffset = -0.1; + scaleFactor = this.options.arrows.to.scaleFactor; + } else { + node1 = this.to; + node2 = this.from; + scaleFactor = this.options.arrows.middle.scaleFactor; + } + + // if not connected to itself + if (node1 != node2) { + if (position !== "middle") { + // draw arrow head + if (this.options.smooth.enabled === true) { + arrowPos = this.findBorderPosition(node1, ctx, { via: viaNode }); + var guidePos = this.getPoint(Math.max(0, Math.min(1, arrowPos.t + guideOffset)), viaNode); + angle = Math.atan2(arrowPos.y - guidePos.y, arrowPos.x - guidePos.x); + } else { + angle = Math.atan2(node1.y - node2.y, node1.x - node2.x); + arrowPos = this.findBorderPosition(node1, ctx); + } + } else { + angle = Math.atan2(node1.y - node2.y, node1.x - node2.x); + arrowPos = this.getPoint(0.6, viaNode); // this is 0.6 to account for the size of the arrow. + } + // draw arrow at the end of the line + length = (10 + 5 * this.options.width) * scaleFactor; + ctx.arrow(arrowPos.x, arrowPos.y, angle, length); + ctx.fill(); ctx.stroke(); - ctx.clip(); + } else { + // draw circle + var _angle = undefined, + point = undefined; - this._drawImageAtPosition(ctx); + var _getCircleData5 = this._getCircleData(ctx); - ctx.restore(); + var _getCircleData52 = _slicedToArray(_getCircleData5, 3); - this.boundingBox.top = y - this.options.size; - this.boundingBox.left = x - this.options.size; - this.boundingBox.right = x + this.options.size; - this.boundingBox.bottom = y + this.options.size; + var x = _getCircleData52[0]; + var y = _getCircleData52[1]; + var radius = _getCircleData52[2]; - this._drawImageLabel(ctx, x, y, selected); + if (position === "from") { + point = this.findBorderPosition(this.from, ctx, { x: x, y: y, low: 0.25, high: 0.6, direction: -1 }); + _angle = point.t * -2 * Math.PI + 1.5 * Math.PI + 0.1 * Math.PI; + } else if (position === "to") { + point = this.findBorderPosition(this.from, ctx, { x: x, y: y, low: 0.6, high: 1, direction: 1 }); + _angle = point.t * -2 * Math.PI + 1.5 * Math.PI - 1.1 * Math.PI; + } else { + point = this._pointOnCircle(x, y, radius, 0.175); + _angle = 3.9269908169872414; // === 0.175 * -2 * Math.PI + 1.5 * Math.PI + 0.1 * Math.PI; + } - this.boundingBox.left = Math.min(this.boundingBox.left, this.labelModule.size.left); - this.boundingBox.right = Math.max(this.boundingBox.right, this.labelModule.size.left + this.labelModule.size.width); - this.boundingBox.bottom = Math.max(this.boundingBox.bottom, this.boundingBox.bottom + this.labelModule.size.height); - }, - writable: true, - configurable: true - }, - distanceToBorder: { - value: function distanceToBorder(ctx, angle) { - this.resize(ctx); - return this._distanceToBorder(angle); - }, - writable: true, - configurable: true + // draw the arrowhead + var _length = (10 + 5 * this.options.width) * scaleFactor; + ctx.arrow(point.x, point.y, _angle, _length); + ctx.fill(); + ctx.stroke(); + } } - }); + }]); - return CircularImage; - })(CircleImageBase); + return EdgeBase; + })(); - module.exports = CircularImage; + exports["default"] = EdgeBase; + module.exports = exports["default"]; /***/ }, -/* 85 */ +/* 90 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; - var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; - var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); - var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var _inherits = function (subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; - var NodeBase = _interopRequire(__webpack_require__(97)); + Object.defineProperty(exports, '__esModule', { + value: true + }); - var Database = (function (NodeBase) { - function Database(options, body, labelModule) { - _classCallCheck(this, Database); + var _NodeBase2 = __webpack_require__(104); - _get(Object.getPrototypeOf(Database.prototype), "constructor", this).call(this, options, body, labelModule); + var _NodeBase3 = _interopRequireWildcard(_NodeBase2); + + 'use strict'; + + var Box = (function (_NodeBase) { + function Box(options, body, labelModule) { + _classCallCheck(this, Box); + + _get(Object.getPrototypeOf(Box.prototype), 'constructor', this).call(this, options, body, labelModule); } - _inherits(Database, NodeBase); + _inherits(Box, _NodeBase); - _prototypeProperties(Database, null, { - resize: { - value: function resize(ctx, selected) { - if (this.width === undefined) { - var margin = 5; - var textSize = this.labelModule.getTextSize(ctx, selected); - var size = textSize.width + 2 * margin; - this.width = size; - this.height = size; - } - }, - writable: true, - configurable: true - }, - draw: { - value: function draw(ctx, x, y, selected, hover) { - this.resize(ctx, selected); - this.left = x - this.width / 2; - this.top = y - this.height / 2; - - var borderWidth = this.options.borderWidth; - var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; - - ctx.strokeStyle = selected ? this.options.color.highlight.border : 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); - - ctx.fillStyle = selected ? this.options.color.highlight.background : hover ? this.options.color.hover.background : this.options.color.background; - ctx.database(x - this.width / 2, y - this.height * 0.5, this.width, this.height); - ctx.fill(); - ctx.stroke(); + _createClass(Box, [{ + key: 'resize', + value: function resize(ctx) { + if (this.width === undefined) { + var margin = 5; + var textSize = this.labelModule.getTextSize(ctx, this.selected); + this.width = textSize.width + 2 * margin; + this.height = textSize.height + 2 * margin; + } + } + }, { + key: 'draw', + value: function draw(ctx, x, y, selected, hover) { + this.resize(ctx); + this.left = x - this.width / 2; + this.top = y - this.height / 2; - 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 borderWidth = this.options.borderWidth; + var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; - this.labelModule.draw(ctx, x, y, selected); - }, - writable: true, - configurable: true - }, - distanceToBorder: { - value: function distanceToBorder(ctx, angle) { - this.resize(ctx); - 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); - }, - writable: true, - configurable: true + ctx.strokeStyle = selected ? this.options.color.highlight.border : hover ? this.options.color.hover.border : this.options.color.border; + ctx.lineWidth = selected ? selectionLineWidth : borderWidth; + ctx.lineWidth /= this.body.view.scale; + ctx.lineWidth = Math.min(this.width, ctx.lineWidth); + + ctx.fillStyle = selected ? this.options.color.highlight.background : hover ? this.options.color.hover.background : this.options.color.background; + + ctx.roundRect(this.left, this.top, this.width, this.height, this.options.size); + ctx.fill(); + ctx.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.labelModule.draw(ctx, x, y, selected); } - }); + }, { + key: 'distanceToBorder', + value: function distanceToBorder(ctx, angle) { + this.resize(ctx); + 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); + } + }]); - return Database; - })(NodeBase); + return Box; + })(_NodeBase3['default']); - module.exports = Database; + exports['default'] = Box; + module.exports = exports['default']; /***/ }, -/* 86 */ +/* 91 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; - var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; - var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); - var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var _inherits = function (subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; - var ShapeBase = _interopRequire(__webpack_require__(99)); + Object.defineProperty(exports, '__esModule', { + value: true + }); - var Diamond = (function (ShapeBase) { - function Diamond(options, body, labelModule) { - _classCallCheck(this, Diamond); + var _CircleImageBase2 = __webpack_require__(105); - _get(Object.getPrototypeOf(Diamond.prototype), "constructor", this).call(this, options, body, labelModule); + var _CircleImageBase3 = _interopRequireWildcard(_CircleImageBase2); + + 'use strict'; + + var Circle = (function (_CircleImageBase) { + function Circle(options, body, labelModule) { + _classCallCheck(this, Circle); + + _get(Object.getPrototypeOf(Circle.prototype), 'constructor', this).call(this, options, body, labelModule); } - _inherits(Diamond, ShapeBase); + _inherits(Circle, _CircleImageBase); - _prototypeProperties(Diamond, null, { - resize: { - value: function resize(ctx) { - this._resizeShape(); - }, - writable: true, - configurable: true - }, - draw: { - value: function draw(ctx, x, y, selected, hover) { - this._drawShape(ctx, "diamond", 4, x, y, selected, hover); - }, - writable: true, - configurable: true - }, - distanceToBorder: { - value: function distanceToBorder(ctx, angle) { - return this._distanceToBorder(angle); - }, - writable: true, - configurable: true + _createClass(Circle, [{ + key: 'resize', + value: function resize(ctx, selected) { + if (this.width === undefined) { + var margin = 5; + var textSize = this.labelModule.getTextSize(ctx, selected); + var diameter = Math.max(textSize.width, textSize.height) + 2 * margin; + this.options.size = diameter / 2; + + this.width = diameter; + this.height = diameter; + } } - }); + }, { + key: 'draw', + value: function draw(ctx, x, y, selected, hover) { + this.resize(ctx, selected); + this.left = x - this.width / 2; + this.top = y - this.height / 2; - return Diamond; - })(ShapeBase); + this._drawRawCircle(ctx, x, y, selected, hover, this.options.size); + + this.boundingBox.top = y - this.options.size; + this.boundingBox.left = x - this.options.size; + this.boundingBox.right = x + this.options.size; + this.boundingBox.bottom = y + this.options.size; + + this.labelModule.draw(ctx, x, y, selected); + } + }, { + key: 'distanceToBorder', + value: function distanceToBorder(ctx, angle) { + this.resize(ctx); + 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); + } + }]); + + return Circle; + })(_CircleImageBase3['default']); - module.exports = Diamond; + exports['default'] = Circle; + module.exports = exports['default']; /***/ }, -/* 87 */ +/* 92 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; + + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; + + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + + var _inherits = function (subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + + Object.defineProperty(exports, '__esModule', { + value: true + }); + + var _CircleImageBase2 = __webpack_require__(105); + + var _CircleImageBase3 = _interopRequireWildcard(_CircleImageBase2); + + 'use strict'; + + var CircularImage = (function (_CircleImageBase) { + function CircularImage(options, body, labelModule, imageObj) { + _classCallCheck(this, CircularImage); + + _get(Object.getPrototypeOf(CircularImage.prototype), 'constructor', this).call(this, options, body, labelModule); + this.imageObj = imageObj; + this._swapToImageResizeWhenImageLoaded = true; + } - var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; + _inherits(CircularImage, _CircleImageBase); - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; + _createClass(CircularImage, [{ + key: 'resize', + value: function resize() { + if (this.imageObj.src === undefined || this.imageObj.width === undefined || this.imageObj.height === undefined) { + if (!this.width) { + var diameter = this.options.size * 2; + this.width = diameter; + this.height = diameter; + this._swapToImageResizeWhenImageLoaded = true; + } + } else { + if (this._swapToImageResizeWhenImageLoaded) { + this.width = undefined; + this.height = undefined; + this._swapToImageResizeWhenImageLoaded = false; + } + this._resizeImage(); + } + } + }, { + key: 'draw', + value: function draw(ctx, x, y, selected, hover) { + this.resize(); - var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + this.left = x - this.width / 2; + this.top = y - this.height / 2; - var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + var size = Math.min(0.5 * this.height, 0.5 * this.width); + this._drawRawCircle(ctx, x, y, selected, hover, size); - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + ctx.save(); + ctx.circle(x, y, size); + ctx.stroke(); + ctx.clip(); - var ShapeBase = _interopRequire(__webpack_require__(99)); + this._drawImageAtPosition(ctx); - var Dot = (function (ShapeBase) { - function Dot(options, body, labelModule) { - _classCallCheck(this, Dot); + ctx.restore(); - _get(Object.getPrototypeOf(Dot.prototype), "constructor", this).call(this, options, body, labelModule); - } + this.boundingBox.top = y - this.options.size; + this.boundingBox.left = x - this.options.size; + this.boundingBox.right = x + this.options.size; + this.boundingBox.bottom = y + this.options.size; - _inherits(Dot, ShapeBase); + this._drawImageLabel(ctx, x, y, selected); - _prototypeProperties(Dot, null, { - resize: { - value: function resize(ctx) { - this._resizeShape(); - }, - writable: true, - configurable: true - }, - draw: { - value: function draw(ctx, x, y, selected, hover) { - this._drawShape(ctx, "circle", 2, x, y, selected, hover); - }, - writable: true, - configurable: true - }, - distanceToBorder: { - value: function distanceToBorder(ctx, angle) { - return this.options.size + this.options.borderWidth; - }, - writable: true, - configurable: true + this.boundingBox.left = Math.min(this.boundingBox.left, this.labelModule.size.left); + this.boundingBox.right = Math.max(this.boundingBox.right, this.labelModule.size.left + this.labelModule.size.width); + this.boundingBox.bottom = Math.max(this.boundingBox.bottom, this.boundingBox.bottom + this.labelModule.size.height); } - }); + }, { + key: 'distanceToBorder', + value: function distanceToBorder(ctx, angle) { + this.resize(ctx); + return this._distanceToBorder(angle); + } + }]); - return Dot; - })(ShapeBase); + return CircularImage; + })(_CircleImageBase3['default']); - module.exports = Dot; + exports['default'] = CircularImage; + module.exports = exports['default']; /***/ }, -/* 88 */ +/* 93 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; - var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; - var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); - var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var _inherits = function (subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; - var NodeBase = _interopRequire(__webpack_require__(97)); + Object.defineProperty(exports, '__esModule', { + value: true + }); - var Ellipse = (function (NodeBase) { - function Ellipse(options, body, labelModule) { - _classCallCheck(this, Ellipse); + var _NodeBase2 = __webpack_require__(104); - _get(Object.getPrototypeOf(Ellipse.prototype), "constructor", this).call(this, options, body, labelModule); - } + var _NodeBase3 = _interopRequireWildcard(_NodeBase2); - _inherits(Ellipse, NodeBase); + 'use strict'; - _prototypeProperties(Ellipse, null, { - resize: { - value: function resize(ctx, selected) { - if (this.width === undefined) { - var textSize = this.labelModule.getTextSize(ctx, selected); + var Database = (function (_NodeBase) { + function Database(options, body, labelModule) { + _classCallCheck(this, Database); - this.width = textSize.width * 1.5; - this.height = textSize.height * 2; - if (this.width < this.height) { - this.width = this.height; - } - } - }, - writable: true, - configurable: true - }, - draw: { - value: function draw(ctx, x, y, selected, hover) { - this.resize(ctx, selected); - this.left = x - this.width / 2; - this.top = y - this.height / 2; + _get(Object.getPrototypeOf(Database.prototype), 'constructor', this).call(this, options, body, labelModule); + } - var borderWidth = this.options.borderWidth; - var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; + _inherits(Database, _NodeBase); - ctx.strokeStyle = selected ? this.options.color.highlight.border : hover ? this.options.color.hover.border : this.options.color.border; + _createClass(Database, [{ + key: 'resize', + value: function resize(ctx, selected) { + if (this.width === undefined) { + var margin = 5; + var textSize = this.labelModule.getTextSize(ctx, selected); + var size = textSize.width + 2 * margin; + this.width = size; + this.height = size; + } + } + }, { + key: 'draw', + value: function draw(ctx, x, y, selected, hover) { + this.resize(ctx, selected); + this.left = x - this.width / 2; + this.top = y - this.height / 2; - ctx.lineWidth = selected ? selectionLineWidth : borderWidth; - ctx.lineWidth /= this.body.view.scale; - ctx.lineWidth = Math.min(this.width, ctx.lineWidth); + var borderWidth = this.options.borderWidth; + var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; - ctx.fillStyle = selected ? this.options.color.highlight.background : hover ? this.options.color.hover.background : this.options.color.background; - ctx.ellipse(this.left, this.top, this.width, this.height); - ctx.fill(); - ctx.stroke(); + ctx.strokeStyle = selected ? this.options.color.highlight.border : 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); - this.boundingBox.left = this.left; - this.boundingBox.top = this.top; - this.boundingBox.bottom = this.top + this.height; - this.boundingBox.right = this.left + this.width; + ctx.fillStyle = selected ? this.options.color.highlight.background : hover ? this.options.color.hover.background : this.options.color.background; + ctx.database(x - this.width / 2, y - this.height * 0.5, this.width, this.height); + ctx.fill(); + ctx.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.labelModule.draw(ctx, x, y, selected); - }, - writable: true, - configurable: true - }, - distanceToBorder: { - value: function distanceToBorder(ctx, angle) { - this.resize(ctx); - 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); - }, - writable: true, - configurable: true + this.labelModule.draw(ctx, x, y, selected); } - }); + }, { + key: 'distanceToBorder', + value: function distanceToBorder(ctx, angle) { + this.resize(ctx); + 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); + } + }]); - return Ellipse; - })(NodeBase); + return Database; + })(_NodeBase3['default']); - module.exports = Ellipse; + exports['default'] = Database; + module.exports = exports['default']; /***/ }, -/* 89 */ +/* 94 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; - - var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; - - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; - - var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + 'use strict'; - var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; - var NodeBase = _interopRequire(__webpack_require__(97)); + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); - var Icon = (function (NodeBase) { - function Icon(options, body, labelModule) { - _classCallCheck(this, Icon); + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - _get(Object.getPrototypeOf(Icon.prototype), "constructor", this).call(this, options, body, labelModule); - } + var _inherits = function (subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; - _inherits(Icon, NodeBase); + Object.defineProperty(exports, '__esModule', { + value: true + }); - _prototypeProperties(Icon, null, { - resize: { - value: function resize(ctx) { - if (this.width === undefined) { - var margin = 5; - var iconSize = { - width: Number(this.options.icon.size), - height: Number(this.options.icon.size) - }; - this.width = iconSize.width + 2 * margin; - this.height = iconSize.height + 2 * margin; - } - }, - writable: true, - configurable: true - }, - draw: { - value: function draw(ctx, x, y, selected, hover) { - this.resize(ctx); - this.options.icon.size = this.options.icon.size || 50; + var _ShapeBase2 = __webpack_require__(106); - this.left = x - this.width * 0.5; - this.top = y - this.height * 0.5; - this._icon(ctx, x, y, selected); + var _ShapeBase3 = _interopRequireWildcard(_ShapeBase2); + 'use strict'; - this.boundingBox.top = y - this.options.icon.size * 0.5; - this.boundingBox.left = x - this.options.icon.size * 0.5; - this.boundingBox.right = x + this.options.icon.size * 0.5; - this.boundingBox.bottom = y + this.options.icon.size * 0.5; + var Diamond = (function (_ShapeBase) { + function Diamond(options, body, labelModule) { + _classCallCheck(this, Diamond); - if (this.options.label !== undefined) { - var iconTextSpacing = 5; - this.labelModule.draw(ctx, x, y + this.height * 0.5 + iconTextSpacing, selected); - this.boundingBox.left = Math.min(this.boundingBox.left, this.labelModule.size.left); - this.boundingBox.right = Math.max(this.boundingBox.right, this.labelModule.size.left + this.labelModule.size.width); - this.boundingBox.bottom = Math.max(this.boundingBox.bottom, this.boundingBox.bottom + this.labelModule.size.height); - } - }, - writable: true, - configurable: true - }, - _icon: { - value: function _icon(ctx, x, y, selected) { - var iconSize = Number(this.options.icon.size); - var relativeIconSize = iconSize * this.body.view.scale; + _get(Object.getPrototypeOf(Diamond.prototype), 'constructor', this).call(this, options, body, labelModule); + } - if (this.options.icon.code && relativeIconSize > this.options.scaling.label.drawThreshold - 1) { - ctx.font = (selected ? "bold " : "") + iconSize + "px " + this.options.icon.face; + _inherits(Diamond, _ShapeBase); - // draw icon - ctx.fillStyle = this.options.icon.color || "black"; - ctx.textAlign = "center"; - ctx.textBaseline = "middle"; - ctx.fillText(this.options.icon.code, x, y); - } - }, - writable: true, - configurable: true - }, - distanceToBorder: { - value: function distanceToBorder(ctx, angle) { - this.resize(ctx); - this._distanceToBorder(angle); - }, - writable: true, - configurable: true + _createClass(Diamond, [{ + key: 'resize', + value: function resize(ctx) { + this._resizeShape(); } - }); + }, { + key: 'draw', + value: function draw(ctx, x, y, selected, hover) { + this._drawShape(ctx, 'diamond', 4, x, y, selected, hover); + } + }, { + key: 'distanceToBorder', + value: function distanceToBorder(ctx, angle) { + return this._distanceToBorder(angle); + } + }]); - return Icon; - })(NodeBase); + return Diamond; + })(_ShapeBase3['default']); - module.exports = Icon; + exports['default'] = Diamond; + module.exports = exports['default']; /***/ }, -/* 90 */ +/* 95 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; - var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; - var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); - var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var _inherits = function (subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; - var CircleImageBase = _interopRequire(__webpack_require__(98)); + Object.defineProperty(exports, '__esModule', { + value: true + }); - var Image = (function (CircleImageBase) { - function Image(options, body, labelModule, imageObj) { - _classCallCheck(this, Image); + var _ShapeBase2 = __webpack_require__(106); - _get(Object.getPrototypeOf(Image.prototype), "constructor", this).call(this, options, body, labelModule); - this.imageObj = imageObj; - } + var _ShapeBase3 = _interopRequireWildcard(_ShapeBase2); - _inherits(Image, CircleImageBase); + 'use strict'; - _prototypeProperties(Image, null, { - resize: { - value: function resize() { - this._resizeImage(); - }, - writable: true, - configurable: true - }, - draw: { - value: function draw(ctx, x, y, selected, hover) { - this.resize(); - this.left = x - this.width / 2; - this.top = y - this.height / 2; + var Dot = (function (_ShapeBase) { + function Dot(options, body, labelModule) { + _classCallCheck(this, Dot); - this._drawImageAtPosition(ctx); + _get(Object.getPrototypeOf(Dot.prototype), 'constructor', this).call(this, options, body, labelModule); + } - this.boundingBox.top = this.top; - this.boundingBox.left = this.left; - this.boundingBox.right = this.left + this.width; - this.boundingBox.bottom = this.top + this.height; + _inherits(Dot, _ShapeBase); - this._drawImageLabel(ctx, x, y, selected || hover); - this.boundingBox.left = Math.min(this.boundingBox.left, this.labelModule.size.left); - this.boundingBox.right = Math.max(this.boundingBox.right, this.labelModule.size.left + this.labelModule.size.width); - this.boundingBox.bottom = Math.max(this.boundingBox.bottom, this.boundingBox.bottom + this.labelModule.size.height); - }, - writable: true, - configurable: true - }, - distanceToBorder: { - value: function distanceToBorder(ctx, angle) { - this.resize(ctx); - 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); - }, - writable: true, - configurable: true + _createClass(Dot, [{ + key: 'resize', + value: function resize(ctx) { + this._resizeShape(); } - }); + }, { + key: 'draw', + value: function draw(ctx, x, y, selected, hover) { + this._drawShape(ctx, 'circle', 2, x, y, selected, hover); + } + }, { + key: 'distanceToBorder', + value: function distanceToBorder(ctx, angle) { + return this.options.size + this.options.borderWidth; + } + }]); - return Image; - })(CircleImageBase); + return Dot; + })(_ShapeBase3['default']); - module.exports = Image; + exports['default'] = Dot; + module.exports = exports['default']; /***/ }, -/* 91 */ +/* 96 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; - var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; - var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); - var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var _inherits = function (subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; - var ShapeBase = _interopRequire(__webpack_require__(99)); + Object.defineProperty(exports, '__esModule', { + value: true + }); - var Square = (function (ShapeBase) { - function Square(options, body, labelModule) { - _classCallCheck(this, Square); + var _NodeBase2 = __webpack_require__(104); + + var _NodeBase3 = _interopRequireWildcard(_NodeBase2); + + 'use strict'; + + var Ellipse = (function (_NodeBase) { + function Ellipse(options, body, labelModule) { + _classCallCheck(this, Ellipse); - _get(Object.getPrototypeOf(Square.prototype), "constructor", this).call(this, options, body, labelModule); + _get(Object.getPrototypeOf(Ellipse.prototype), 'constructor', this).call(this, options, body, labelModule); } - _inherits(Square, ShapeBase); + _inherits(Ellipse, _NodeBase); - _prototypeProperties(Square, null, { - resize: { - value: function resize() { - this._resizeShape(); - }, - writable: true, - configurable: true - }, - draw: { - value: function draw(ctx, x, y, selected, hover) { - this._drawShape(ctx, "square", 2, x, y, selected, hover); - }, - writable: true, - configurable: true - }, - distanceToBorder: { - value: function distanceToBorder(ctx, angle) { - this.resize(ctx); - return this._distanceToBorder(angle); - }, - writable: true, - configurable: true + _createClass(Ellipse, [{ + key: 'resize', + value: function resize(ctx, selected) { + if (this.width === undefined) { + var textSize = this.labelModule.getTextSize(ctx, selected); + + this.width = textSize.width * 1.5; + this.height = textSize.height * 2; + if (this.width < this.height) { + this.width = this.height; + } + } } - }); + }, { + key: 'draw', + value: function draw(ctx, x, y, selected, hover) { + this.resize(ctx, selected); + this.left = x - this.width / 2; + this.top = y - this.height / 2; - return Square; - })(ShapeBase); + var borderWidth = this.options.borderWidth; + var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; - module.exports = Square; + ctx.strokeStyle = selected ? this.options.color.highlight.border : hover ? this.options.color.hover.border : this.options.color.border; -/***/ }, -/* 92 */ -/***/ function(module, exports, __webpack_require__) { + ctx.lineWidth = selected ? selectionLineWidth : borderWidth; + ctx.lineWidth /= this.body.view.scale; + ctx.lineWidth = Math.min(this.width, ctx.lineWidth); - "use strict"; + ctx.fillStyle = selected ? this.options.color.highlight.background : hover ? this.options.color.hover.background : this.options.color.background; + ctx.ellipse(this.left, this.top, this.width, this.height); + ctx.fill(); + ctx.stroke(); - var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; + this.boundingBox.left = this.left; + this.boundingBox.top = this.top; + this.boundingBox.bottom = this.top + this.height; + this.boundingBox.right = this.left + this.width; - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; + this.labelModule.draw(ctx, x, y, selected); + } + }, { + key: 'distanceToBorder', + value: function distanceToBorder(ctx, angle) { + this.resize(ctx); + var a = this.width / 2; + var b = this.height / 2; + var w = Math.sin(angle) * a; + var h = Math.cos(angle) * b; + return a * b / Math.sqrt(w * w + h * h); + } + }]); - var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + return Ellipse; + })(_NodeBase3['default']); - var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + exports['default'] = Ellipse; + module.exports = exports['default']; - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; +/***/ }, +/* 97 */ +/***/ function(module, exports, __webpack_require__) { - var ShapeBase = _interopRequire(__webpack_require__(99)); + 'use strict'; - var Star = (function (ShapeBase) { - function Star(options, body, labelModule) { - _classCallCheck(this, Star); + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; - _get(Object.getPrototypeOf(Star.prototype), "constructor", this).call(this, options, body, labelModule); - } + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; - _inherits(Star, ShapeBase); + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); - _prototypeProperties(Star, null, { - resize: { - value: function resize(ctx) { - this._resizeShape(); - }, - writable: true, - configurable: true - }, - draw: { - value: function draw(ctx, x, y, selected, hover) { - this._drawShape(ctx, "star", 4, x, y, selected, hover); - }, - writable: true, - configurable: true - }, - distanceToBorder: { - value: function distanceToBorder(ctx, angle) { - return this._distanceToBorder(angle); - }, - writable: true, - configurable: true - } - }); + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - return Star; - })(ShapeBase); + var _inherits = function (subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; - module.exports = Star; + Object.defineProperty(exports, '__esModule', { + value: true + }); -/***/ }, -/* 93 */ -/***/ function(module, exports, __webpack_require__) { + var _NodeBase2 = __webpack_require__(104); - "use strict"; + var _NodeBase3 = _interopRequireWildcard(_NodeBase2); - var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; + 'use strict'; - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; + var Icon = (function (_NodeBase) { + function Icon(options, body, labelModule) { + _classCallCheck(this, Icon); - var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + _get(Object.getPrototypeOf(Icon.prototype), 'constructor', this).call(this, options, body, labelModule); + } - var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + _inherits(Icon, _NodeBase); - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + _createClass(Icon, [{ + key: 'resize', + value: function resize(ctx) { + if (this.width === undefined) { + var margin = 5; + var iconSize = { + width: Number(this.options.icon.size), + height: Number(this.options.icon.size) + }; + this.width = iconSize.width + 2 * margin; + this.height = iconSize.height + 2 * margin; + } + } + }, { + key: 'draw', + value: function draw(ctx, x, y, selected, hover) { + this.resize(ctx); + this.options.icon.size = this.options.icon.size || 50; - var NodeBase = _interopRequire(__webpack_require__(97)); + this.left = x - this.width * 0.5; + this.top = y - this.height * 0.5; + this._icon(ctx, x, y, selected); - var Text = (function (NodeBase) { - function Text(options, body, labelModule) { - _classCallCheck(this, Text); + this.boundingBox.top = y - this.options.icon.size * 0.5; + this.boundingBox.left = x - this.options.icon.size * 0.5; + this.boundingBox.right = x + this.options.icon.size * 0.5; + this.boundingBox.bottom = y + this.options.icon.size * 0.5; - _get(Object.getPrototypeOf(Text.prototype), "constructor", this).call(this, options, body, labelModule); - } + if (this.options.label !== undefined) { + var iconTextSpacing = 5; + this.labelModule.draw(ctx, x, y + this.height * 0.5 + iconTextSpacing, selected); + this.boundingBox.left = Math.min(this.boundingBox.left, this.labelModule.size.left); + this.boundingBox.right = Math.max(this.boundingBox.right, this.labelModule.size.left + this.labelModule.size.width); + this.boundingBox.bottom = Math.max(this.boundingBox.bottom, this.boundingBox.bottom + this.labelModule.size.height); + } + } + }, { + key: '_icon', + value: function _icon(ctx, x, y, selected) { + var iconSize = Number(this.options.icon.size); + var relativeIconSize = iconSize * this.body.view.scale; - _inherits(Text, NodeBase); + if (this.options.icon.code && relativeIconSize > this.options.scaling.label.drawThreshold - 1) { + ctx.font = (selected ? 'bold ' : '') + iconSize + 'px ' + this.options.icon.face; - _prototypeProperties(Text, null, { - resize: { - value: function resize(ctx, selected) { - if (this.width === undefined) { - var margin = 5; - var textSize = this.labelModule.getTextSize(ctx, selected); - this.width = textSize.width + 2 * margin; - this.height = textSize.height + 2 * margin; - } - }, - writable: true, - configurable: true - }, - draw: { - value: function draw(ctx, x, y, selected, hover) { - this.resize(ctx, selected || hover); - this.left = x - this.width / 2; - this.top = y - this.height / 2; - - this.labelModule.draw(ctx, x, y, selected || hover); - - this.boundingBox.top = this.top; - this.boundingBox.left = this.left; - this.boundingBox.right = this.left + this.width; - this.boundingBox.bottom = this.top + this.height; - }, - writable: true, - configurable: true - }, - distanceToBorder: { - value: function distanceToBorder(ctx, angle) { - this.resize(ctx); - return this._distanceToBorder(angle); - }, - writable: true, - configurable: true + // draw icon + ctx.fillStyle = this.options.icon.color || 'black'; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + ctx.fillText(this.options.icon.code, x, y); + } } - }); + }, { + key: 'distanceToBorder', + value: function distanceToBorder(ctx, angle) { + this.resize(ctx); + this._distanceToBorder(angle); + } + }]); - return Text; - })(NodeBase); + return Icon; + })(_NodeBase3['default']); - module.exports = Text; + exports['default'] = Icon; + module.exports = exports['default']; /***/ }, -/* 94 */ +/* 98 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; - var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; - var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); - var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var _inherits = function (subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + + Object.defineProperty(exports, '__esModule', { + value: true + }); - var ShapeBase = _interopRequire(__webpack_require__(99)); + var _CircleImageBase2 = __webpack_require__(105); - var Triangle = (function (ShapeBase) { - function Triangle(options, body, labelModule) { - _classCallCheck(this, Triangle); + var _CircleImageBase3 = _interopRequireWildcard(_CircleImageBase2); + + 'use strict'; - _get(Object.getPrototypeOf(Triangle.prototype), "constructor", this).call(this, options, body, labelModule); + var Image = (function (_CircleImageBase) { + function Image(options, body, labelModule, imageObj) { + _classCallCheck(this, Image); + + _get(Object.getPrototypeOf(Image.prototype), 'constructor', this).call(this, options, body, labelModule); + this.imageObj = imageObj; } - _inherits(Triangle, ShapeBase); + _inherits(Image, _CircleImageBase); - _prototypeProperties(Triangle, null, { - resize: { - value: function resize(ctx) { - this._resizeShape(); - }, - writable: true, - configurable: true - }, - draw: { - value: function draw(ctx, x, y, selected, hover) { - this._drawShape(ctx, "triangle", 3, x, y, selected, hover); - }, - writable: true, - configurable: true - }, - distanceToBorder: { - value: function distanceToBorder(ctx, angle) { - return this._distanceToBorder(angle); - }, - writable: true, - configurable: true + _createClass(Image, [{ + key: 'resize', + value: function resize() { + this._resizeImage(); } - }); + }, { + key: 'draw', + value: function draw(ctx, x, y, selected, hover) { + this.resize(); + this.left = x - this.width / 2; + this.top = y - this.height / 2; - return Triangle; - })(ShapeBase); + this._drawImageAtPosition(ctx); - module.exports = Triangle; + this.boundingBox.top = this.top; + this.boundingBox.left = this.left; + this.boundingBox.right = this.left + this.width; + this.boundingBox.bottom = this.top + this.height; -/***/ }, -/* 95 */ -/***/ function(module, exports, __webpack_require__) { + this._drawImageLabel(ctx, x, y, selected || hover); + this.boundingBox.left = Math.min(this.boundingBox.left, this.labelModule.size.left); + this.boundingBox.right = Math.max(this.boundingBox.right, this.labelModule.size.left + this.labelModule.size.width); + this.boundingBox.bottom = Math.max(this.boundingBox.bottom, this.boundingBox.bottom + this.labelModule.size.height); + } + }, { + key: 'distanceToBorder', + value: function distanceToBorder(ctx, angle) { + this.resize(ctx); + 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); + } + }]); - "use strict"; + return Image; + })(_CircleImageBase3['default']); - var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; + exports['default'] = Image; + module.exports = exports['default']; - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; +/***/ }, +/* 99 */ +/***/ function(module, exports, __webpack_require__) { - var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + 'use strict'; - var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; - var ShapeBase = _interopRequire(__webpack_require__(99)); + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); - var TriangleDown = (function (ShapeBase) { - function TriangleDown(options, body, labelModule) { - _classCallCheck(this, TriangleDown); + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - _get(Object.getPrototypeOf(TriangleDown.prototype), "constructor", this).call(this, options, body, labelModule); - } + var _inherits = function (subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; - _inherits(TriangleDown, ShapeBase); + Object.defineProperty(exports, '__esModule', { + value: true + }); - _prototypeProperties(TriangleDown, null, { - resize: { - value: function resize(ctx) { - this._resizeShape(); - }, - writable: true, - configurable: true - }, - draw: { - value: function draw(ctx, x, y, selected, hover) { - this._drawShape(ctx, "triangleDown", 3, x, y, selected, hover); - }, - writable: true, - configurable: true - }, - distanceToBorder: { - value: function distanceToBorder(ctx, angle) { - return this._distanceToBorder(angle); - }, - writable: true, - configurable: true - } - }); + var _ShapeBase2 = __webpack_require__(106); - return TriangleDown; - })(ShapeBase); + var _ShapeBase3 = _interopRequireWildcard(_ShapeBase2); - module.exports = TriangleDown; + 'use strict'; -/***/ }, -/* 96 */ -/***/ function(module, exports, __webpack_require__) { + var Square = (function (_ShapeBase) { + function Square(options, body, labelModule) { + _classCallCheck(this, Square); - "use strict"; + _get(Object.getPrototypeOf(Square.prototype), 'constructor', this).call(this, options, body, labelModule); + } - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; + _inherits(Square, _ShapeBase); - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + _createClass(Square, [{ + key: 'resize', + value: function resize() { + this._resizeShape(); + } + }, { + key: 'draw', + value: function draw(ctx, x, y, selected, hover) { + this._drawShape(ctx, 'square', 2, x, y, selected, hover); + } + }, { + key: 'distanceToBorder', + value: function distanceToBorder(ctx, angle) { + this.resize(ctx); + return this._distanceToBorder(angle); + } + }]); - var Hammer = __webpack_require__(41); - var hammerUtil = __webpack_require__(64); - var util = __webpack_require__(1); + return Square; + })(_ShapeBase3['default']); - var ColorPicker = (function () { - function ColorPicker() { - var pixelRatio = arguments[0] === undefined ? 1 : arguments[0]; - _classCallCheck(this, ColorPicker); + exports['default'] = Square; + module.exports = exports['default']; - this.pixelRatio = pixelRatio; - this.generated = false; - this.centerCoordinates = { x: 289 / 2, y: 289 / 2 }; - this.r = 289 * 0.49; - this.color = { r: 255, g: 255, b: 255, a: 1 }; - this.hueCircle = undefined; - this.initialColor = { r: 255, g: 255, b: 255, a: 1 }; - this.previousColor = undefined; - this.applied = false; +/***/ }, +/* 100 */ +/***/ function(module, exports, __webpack_require__) { - // bound by - this.updateCallback = function () {}; + 'use strict'; - // create all DOM elements - this._create(); - } + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; - _prototypeProperties(ColorPicker, null, { - insertTo: { + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); - /** - * this inserts the colorPicker into a div from the DOM - * @param container - */ - value: function insertTo(container) { - if (this.hammer !== undefined) { - this.hammer.destroy(); - this.hammer = undefined; - } - this.container = container; - this.container.appendChild(this.frame); - this._bindHammer(); + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - this._setSize(); - }, - writable: true, - configurable: true - }, - setCallback: { + var _inherits = function (subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; - /** - * the callback is executed on apply and save. Bind it to the application - * @param callback - */ - value: function setCallback(callback) { - if (typeof callback === "function") { - this.updateCallback = callback; - } else { - throw new Error("Function attempted to set as colorPicker callback is not a function."); - } - }, - writable: true, - configurable: true - }, - _isColorString: { - value: function _isColorString(color) { - var htmlColors = { black: "#000000", navy: "#000080", darkblue: "#00008B", mediumblue: "#0000CD", blue: "#0000FF", darkgreen: "#006400", green: "#008000", teal: "#008080", darkcyan: "#008B8B", deepskyblue: "#00BFFF", darkturquoise: "#00CED1", mediumspringgreen: "#00FA9A", lime: "#00FF00", springgreen: "#00FF7F", aqua: "#00FFFF", cyan: "#00FFFF", midnightblue: "#191970", dodgerblue: "#1E90FF", lightseagreen: "#20B2AA", forestgreen: "#228B22", seagreen: "#2E8B57", darkslategray: "#2F4F4F", limegreen: "#32CD32", mediumseagreen: "#3CB371", turquoise: "#40E0D0", royalblue: "#4169E1", steelblue: "#4682B4", darkslateblue: "#483D8B", mediumturquoise: "#48D1CC", indigo: "#4B0082", darkolivegreen: "#556B2F", cadetblue: "#5F9EA0", cornflowerblue: "#6495ED", mediumaquamarine: "#66CDAA", dimgray: "#696969", slateblue: "#6A5ACD", olivedrab: "#6B8E23", slategray: "#708090", lightslategray: "#778899", mediumslateblue: "#7B68EE", lawngreen: "#7CFC00", chartreuse: "#7FFF00", aquamarine: "#7FFFD4", maroon: "#800000", purple: "#800080", olive: "#808000", gray: "#808080", skyblue: "#87CEEB", lightskyblue: "#87CEFA", blueviolet: "#8A2BE2", darkred: "#8B0000", darkmagenta: "#8B008B", saddlebrown: "#8B4513", darkseagreen: "#8FBC8F", lightgreen: "#90EE90", mediumpurple: "#9370D8", darkviolet: "#9400D3", palegreen: "#98FB98", darkorchid: "#9932CC", yellowgreen: "#9ACD32", sienna: "#A0522D", brown: "#A52A2A", darkgray: "#A9A9A9", lightblue: "#ADD8E6", greenyellow: "#ADFF2F", paleturquoise: "#AFEEEE", lightsteelblue: "#B0C4DE", powderblue: "#B0E0E6", firebrick: "#B22222", darkgoldenrod: "#B8860B", mediumorchid: "#BA55D3", rosybrown: "#BC8F8F", darkkhaki: "#BDB76B", silver: "#C0C0C0", mediumvioletred: "#C71585", indianred: "#CD5C5C", peru: "#CD853F", chocolate: "#D2691E", tan: "#D2B48C", lightgrey: "#D3D3D3", palevioletred: "#D87093", thistle: "#D8BFD8", orchid: "#DA70D6", goldenrod: "#DAA520", crimson: "#DC143C", gainsboro: "#DCDCDC", plum: "#DDA0DD", burlywood: "#DEB887", lightcyan: "#E0FFFF", lavender: "#E6E6FA", darksalmon: "#E9967A", violet: "#EE82EE", palegoldenrod: "#EEE8AA", lightcoral: "#F08080", khaki: "#F0E68C", aliceblue: "#F0F8FF", honeydew: "#F0FFF0", azure: "#F0FFFF", sandybrown: "#F4A460", wheat: "#F5DEB3", beige: "#F5F5DC", whitesmoke: "#F5F5F5", mintcream: "#F5FFFA", ghostwhite: "#F8F8FF", salmon: "#FA8072", antiquewhite: "#FAEBD7", linen: "#FAF0E6", lightgoldenrodyellow: "#FAFAD2", oldlace: "#FDF5E6", red: "#FF0000", fuchsia: "#FF00FF", magenta: "#FF00FF", deeppink: "#FF1493", orangered: "#FF4500", tomato: "#FF6347", hotpink: "#FF69B4", coral: "#FF7F50", darkorange: "#FF8C00", lightsalmon: "#FFA07A", orange: "#FFA500", lightpink: "#FFB6C1", pink: "#FFC0CB", gold: "#FFD700", peachpuff: "#FFDAB9", navajowhite: "#FFDEAD", moccasin: "#FFE4B5", bisque: "#FFE4C4", mistyrose: "#FFE4E1", blanchedalmond: "#FFEBCD", papayawhip: "#FFEFD5", lavenderblush: "#FFF0F5", seashell: "#FFF5EE", cornsilk: "#FFF8DC", lemonchiffon: "#FFFACD", floralwhite: "#FFFAF0", snow: "#FFFAFA", yellow: "#FFFF00", lightyellow: "#FFFFE0", ivory: "#FFFFF0", white: "#FFFFFF" }; - if (typeof color === "string") { - return htmlColors[color]; - } - }, - writable: true, - configurable: true - }, - setColor: { + Object.defineProperty(exports, '__esModule', { + value: true + }); + var _ShapeBase2 = __webpack_require__(106); - /** - * Set the color of the colorPicker - * Supported formats: - * 'red' --> HTML color string - * '#ffffff' --> hex string - * 'rbg(255,255,255)' --> rgb string - * 'rgba(255,255,255,1.0)' --> rgba string - * {r:255,g:255,b:255} --> rgb object - * {r:255,g:255,b:255,a:1.0} --> rgba object - * @param color - * @param setInitial - */ - value: function setColor(color) { - var setInitial = arguments[1] === undefined ? true : arguments[1]; - if (color === "none") { - return; - } + var _ShapeBase3 = _interopRequireWildcard(_ShapeBase2); - var rgba = undefined; + 'use strict'; - // if a html color shorthand is used, convert to hex - var htmlColor = this._isColorString(color); - if (htmlColor !== undefined) { - color = htmlColor; - } + var Star = (function (_ShapeBase) { + function Star(options, body, labelModule) { + _classCallCheck(this, Star); - // check format - if (util.isString(color) === true) { - if (util.isValidRGB(color) === true) { - var rgbaArray = color.substr(4).substr(0, color.length - 5).split(","); - rgba = { r: rgbaArray[0], g: rgbaArray[1], b: rgbaArray[2], a: 1 }; - } else if (util.isValidRGBA(color) === true) { - var rgbaArray = color.substr(5).substr(0, color.length - 6).split(","); - rgba = { r: rgbaArray[0], g: rgbaArray[1], b: rgbaArray[2], a: rgbaArray[3] }; - } else if (util.isValidHex(color) === true) { - var rgbObj = util.hexToRGB(color); - rgba = { r: rgbObj.r, g: rgbObj.g, b: rgbObj.b, a: 1 }; - } - } else { - if (color instanceof Object) { - if (color.r !== undefined && color.g !== undefined && color.b !== undefined) { - var alpha = color.a !== undefined ? color.a : "1.0"; - rgba = { r: color.r, g: color.g, b: color.b, a: alpha }; - } - } - } + _get(Object.getPrototypeOf(Star.prototype), 'constructor', this).call(this, options, body, labelModule); + } - // set color - if (rgba === undefined) { - throw new Error("Unknown color passed to the colorPicker. Supported are strings: rgb, hex, rgba. Object: rgb ({r:r,g:g,b:b,[a:a]}). Supplied: " + JSON.stringify(color)); - } else { - this._setColor(rgba, setInitial); - } - }, - writable: true, - configurable: true - }, - show: { + _inherits(Star, _ShapeBase); + _createClass(Star, [{ + key: 'resize', + value: function resize(ctx) { + this._resizeShape(); + } + }, { + key: 'draw', + value: function draw(ctx, x, y, selected, hover) { + this._drawShape(ctx, 'star', 4, x, y, selected, hover); + } + }, { + key: 'distanceToBorder', + value: function distanceToBorder(ctx, angle) { + return this._distanceToBorder(angle); + } + }]); - /** - * this shows the color picker at a location. The hue circle is constructed once and stored. - * @param x - * @param y - */ - value: function show(x, y) { - this.applied = false; - this.frame.style.display = "block"; - this.frame.style.top = y + "px"; - this.frame.style.left = x + "px"; - this._generateHueCircle(); - }, - writable: true, - configurable: true - }, - _hide: { + return Star; + })(_ShapeBase3['default']); + exports['default'] = Star; + module.exports = exports['default']; - // ------------------------------------------ PRIVATE ----------------------------- // +/***/ }, +/* 101 */ +/***/ function(module, exports, __webpack_require__) { - /** - * Hide the picker. Is called by the cancel button. - * Optional boolean to store the previous color for easy access later on. - * @param storePrevious - * @private - */ - value: function _hide() { - var storePrevious = arguments[0] === undefined ? true : arguments[0]; - // store the previous color for next time; - if (storePrevious === true) { - this.previousColor = util.extend({}, this.color); - } + 'use strict'; - if (this.applied === true) { - this.updateCallback(this.initialColor); - } + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; - this.frame.style.display = "none"; - }, - writable: true, - configurable: true - }, - _save: { + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); - /** - * bound to the save button. Saves and hides. - * @private - */ - value: function _save() { - this.updateCallback(this.color); - this.applied = false; - this._hide(); - }, - writable: true, - configurable: true - }, - _apply: { + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + var _inherits = function (subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; - /** - * Bound to apply button. Saves but does not close. Is undone by the cancel button. - * @private - */ - value: function _apply() { - this.applied = true; - this.updateCallback(this.color); - this._updatePicker(this.color); - }, - writable: true, - configurable: true - }, - _loadLast: { + Object.defineProperty(exports, '__esModule', { + value: true + }); + var _NodeBase2 = __webpack_require__(104); - /** - * load the color from the previous session. - * @private - */ - value: function _loadLast() { - if (this.previousColor !== undefined) { - this.setColor(this.previousColor, false); - } else { - alert("There is no last color to load..."); - } - }, - writable: true, - configurable: true - }, - _setColor: { + var _NodeBase3 = _interopRequireWildcard(_NodeBase2); + 'use strict'; - /** - * set the color, place the picker - * @param rgba - * @param setInitial - * @private - */ - value: function _setColor(rgba) { - var setInitial = arguments[1] === undefined ? true : arguments[1]; - // store the initial color - if (setInitial === true) { - this.initialColor = util.extend({}, rgba); - } + var Text = (function (_NodeBase) { + function Text(options, body, labelModule) { + _classCallCheck(this, Text); - this.color = rgba; - var hsv = util.RGBToHSV(rgba.r, rgba.g, rgba.b); + _get(Object.getPrototypeOf(Text.prototype), 'constructor', this).call(this, options, body, labelModule); + } - var angleConvert = 2 * Math.PI; - var radius = this.r * hsv.s; - var x = this.centerCoordinates.x + radius * Math.sin(angleConvert * hsv.h); - var y = this.centerCoordinates.y + radius * Math.cos(angleConvert * hsv.h); + _inherits(Text, _NodeBase); - this.colorPickerSelector.style.left = x - 0.5 * this.colorPickerSelector.clientWidth + "px"; - this.colorPickerSelector.style.top = y - 0.5 * this.colorPickerSelector.clientHeight + "px"; + _createClass(Text, [{ + key: 'resize', + value: function resize(ctx, selected) { + if (this.width === undefined) { + var margin = 5; + var textSize = this.labelModule.getTextSize(ctx, selected); + this.width = textSize.width + 2 * margin; + this.height = textSize.height + 2 * margin; + } + } + }, { + key: 'draw', + value: function draw(ctx, x, y, selected, hover) { + this.resize(ctx, selected || hover); + this.left = x - this.width / 2; + this.top = y - this.height / 2; - this._updatePicker(rgba); - }, - writable: true, - configurable: true - }, - _setOpacity: { + this.labelModule.draw(ctx, x, y, selected || hover); + this.boundingBox.top = this.top; + this.boundingBox.left = this.left; + this.boundingBox.right = this.left + this.width; + this.boundingBox.bottom = this.top + this.height; + } + }, { + key: 'distanceToBorder', + value: function distanceToBorder(ctx, angle) { + this.resize(ctx); + return this._distanceToBorder(angle); + } + }]); - /** - * bound to opacity control - * @param value - * @private - */ - value: function _setOpacity(value) { - this.color.a = value / 100; - this._updatePicker(this.color); - }, - writable: true, - configurable: true - }, - _setBrightness: { + return Text; + })(_NodeBase3['default']); + exports['default'] = Text; + module.exports = exports['default']; - /** - * bound to brightness control - * @param value - * @private - */ - value: function _setBrightness(value) { - var hsv = util.RGBToHSV(this.color.r, this.color.g, this.color.b); - hsv.v = value / 100; - var rgba = util.HSVToRGB(hsv.h, hsv.s, hsv.v); - rgba.a = this.color.a; - this.color = rgba; - this._updatePicker(); - }, - writable: true, - configurable: true - }, - _updatePicker: { +/***/ }, +/* 102 */ +/***/ function(module, exports, __webpack_require__) { + 'use strict'; - /** - * update the colorpicker. A black circle overlays the hue circle to mimic the brightness decreasing. - * @param rgba - * @private - */ - value: function _updatePicker() { - var rgba = arguments[0] === undefined ? this.color : arguments[0]; - var hsv = util.RGBToHSV(rgba.r, rgba.g, rgba.b); - var ctx = this.colorPickerCanvas.getContext("2d"); - if (this.pixelRation === undefined) { - this.pixelRatio = (window.devicePixelRatio || 1) / (ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1); - } - ctx.setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0); + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; - // clear the canvas - var w = this.colorPickerCanvas.clientWidth; - var h = this.colorPickerCanvas.clientHeight; - ctx.clearRect(0, 0, w, h); + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; - ctx.putImageData(this.hueCircle, 0, 0); - ctx.fillStyle = "rgba(0,0,0," + (1 - hsv.v) + ")"; - ctx.circle(this.centerCoordinates.x, this.centerCoordinates.y, this.r); - ctx.fill(); + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); - this.brightnessRange.value = 100 * hsv.v; - this.opacityRange.value = 100 * rgba.a; + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - this.initialColorDiv.style.backgroundColor = "rgba(" + this.initialColor.r + "," + this.initialColor.g + "," + this.initialColor.b + "," + this.initialColor.a + ")"; - this.newColorDiv.style.backgroundColor = "rgba(" + this.color.r + "," + this.color.g + "," + this.color.b + "," + this.color.a + ")"; - }, - writable: true, - configurable: true - }, - _setSize: { + var _inherits = function (subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + Object.defineProperty(exports, '__esModule', { + value: true + }); - /** - * used by create to set the size of the canvas. - * @private - */ - value: function _setSize() { - this.colorPickerCanvas.style.width = "100%"; - this.colorPickerCanvas.style.height = "100%"; + var _ShapeBase2 = __webpack_require__(106); - this.colorPickerCanvas.width = 289 * this.pixelRatio; - this.colorPickerCanvas.height = 289 * this.pixelRatio; - }, - writable: true, - configurable: true - }, - _create: { + var _ShapeBase3 = _interopRequireWildcard(_ShapeBase2); + 'use strict'; - /** - * create all dom elements - * TODO: cleanup, lots of similar dom elements - * @private - */ - value: function _create() { - var visPrefix = "vis-network-"; - - this.frame = document.createElement("div"); - this.frame.className = visPrefix + "colorPicker-frame"; - - this.colorPickerDiv = document.createElement("div"); - this.colorPickerSelector = document.createElement("div"); - this.colorPickerSelector.className = visPrefix + "colorPicker-selector"; - this.colorPickerDiv.appendChild(this.colorPickerSelector); - - this.colorPickerCanvas = document.createElement("canvas"); - this.colorPickerDiv.appendChild(this.colorPickerCanvas); - - if (!this.colorPickerCanvas.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.colorPickerCanvas.appendChild(noCanvas); - } else { - var ctx = this.colorPickerCanvas.getContext("2d"); - this.pixelRatio = (window.devicePixelRatio || 1) / (ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1); + var Triangle = (function (_ShapeBase) { + function Triangle(options, body, labelModule) { + _classCallCheck(this, Triangle); - this.colorPickerCanvas.getContext("2d").setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0); - } + _get(Object.getPrototypeOf(Triangle.prototype), 'constructor', this).call(this, options, body, labelModule); + } - this.colorPickerDiv.className = visPrefix + "colorPicker-color"; + _inherits(Triangle, _ShapeBase); - this.opacityDiv = document.createElement("div"); - this.opacityDiv.className = visPrefix + "colorPicker-opacity"; + _createClass(Triangle, [{ + key: 'resize', + value: function resize(ctx) { + this._resizeShape(); + } + }, { + key: 'draw', + value: function draw(ctx, x, y, selected, hover) { + this._drawShape(ctx, 'triangle', 3, x, y, selected, hover); + } + }, { + key: 'distanceToBorder', + value: function distanceToBorder(ctx, angle) { + return this._distanceToBorder(angle); + } + }]); - this.brightnessDiv = document.createElement("div"); - this.brightnessDiv.className = visPrefix + "colorPicker-brightness"; + return Triangle; + })(_ShapeBase3['default']); - this.arrowDiv = document.createElement("div"); - this.arrowDiv.className = visPrefix + "colorPicker-arrowDiv"; + exports['default'] = Triangle; + module.exports = exports['default']; - this.opacityRange = document.createElement("input"); - this.opacityRange.type = "range"; - this.opacityRange.min = "0"; - this.opacityRange.max = "100"; - this.opacityRange.value = "100"; - this.opacityRange.className = visPrefix + "configuration range colorPicker"; +/***/ }, +/* 103 */ +/***/ function(module, exports, __webpack_require__) { - this.brightnessRange = document.createElement("input"); - this.brightnessRange.type = "range"; - this.brightnessRange.min = "0"; - this.brightnessRange.max = "100"; - this.brightnessRange.value = "100"; - this.brightnessRange.className = visPrefix + "configuration range colorPicker"; + 'use strict'; - this.opacityDiv.appendChild(this.opacityRange); - this.brightnessDiv.appendChild(this.brightnessRange); + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; - var me = this; - this.opacityRange.onchange = function () { - me._setOpacity(this.value); - }; - this.opacityRange.oninput = function () { - me._setOpacity(this.value); - }; - this.brightnessRange.onchange = function () { - me._setBrightness(this.value); - }; - this.brightnessRange.oninput = function () { - me._setBrightness(this.value); - }; + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; - this.brightnessLabel = document.createElement("div"); - this.brightnessLabel.className = visPrefix + "colorPicker-label brightness"; - this.brightnessLabel.innerHTML = "brightness:"; - - this.opacityLabel = document.createElement("div"); - this.opacityLabel.className = visPrefix + "colorPicker-label opacity"; - this.opacityLabel.innerHTML = "opacity:"; - - this.newColorDiv = document.createElement("div"); - this.newColorDiv.className = visPrefix + "colorPicker-newColor"; - this.newColorDiv.innerHTML = "new"; - - this.initialColorDiv = document.createElement("div"); - this.initialColorDiv.className = visPrefix + "colorPicker-initialColor"; - this.initialColorDiv.innerHTML = "initial"; - - this.cancelButton = document.createElement("div"); - this.cancelButton.className = visPrefix + "colorPicker-button cancel"; - this.cancelButton.innerHTML = "cancel"; - this.cancelButton.onclick = this._hide.bind(this, false); - - this.applyButton = document.createElement("div"); - this.applyButton.className = visPrefix + "colorPicker-button apply"; - this.applyButton.innerHTML = "apply"; - this.applyButton.onclick = this._apply.bind(this); - - this.saveButton = document.createElement("div"); - this.saveButton.className = visPrefix + "colorPicker-button save"; - this.saveButton.innerHTML = "save"; - this.saveButton.onclick = this._save.bind(this); - - this.loadButton = document.createElement("div"); - this.loadButton.className = visPrefix + "colorPicker-button load"; - this.loadButton.innerHTML = "load last"; - this.loadButton.onclick = this._loadLast.bind(this); - - this.frame.appendChild(this.colorPickerDiv); - this.frame.appendChild(this.arrowDiv); - this.frame.appendChild(this.brightnessLabel); - this.frame.appendChild(this.brightnessDiv); - this.frame.appendChild(this.opacityLabel); - this.frame.appendChild(this.opacityDiv); - this.frame.appendChild(this.newColorDiv); - this.frame.appendChild(this.initialColorDiv); - - this.frame.appendChild(this.cancelButton); - this.frame.appendChild(this.applyButton); - this.frame.appendChild(this.saveButton); - this.frame.appendChild(this.loadButton); - }, - writable: true, - configurable: true - }, - _bindHammer: { + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - /** - * bind hammer to the color picker - * @private - */ - value: function _bindHammer() { - var _this = this; - this.drag = {}; - this.pinch = {}; - this.hammer = new Hammer(this.colorPickerCanvas); - this.hammer.get("pinch").set({ enable: true }); - - hammerUtil.onTouch(this.hammer, function (event) { - _this._moveSelector(event); - }); - this.hammer.on("tap", function (event) { - _this._moveSelector(event); - }); - this.hammer.on("panstart", function (event) { - _this._moveSelector(event); - }); - this.hammer.on("panmove", function (event) { - _this._moveSelector(event); - }); - this.hammer.on("panend", function (event) { - _this._moveSelector(event); - }); - }, - writable: true, - configurable: true - }, - _generateHueCircle: { + var _inherits = function (subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + Object.defineProperty(exports, '__esModule', { + value: true + }); - /** - * generate the hue circle. This is relatively heavy (200ms) and is done only once on the first time it is shown. - * @private - */ - value: function _generateHueCircle() { - if (this.generated === false) { - var ctx = this.colorPickerCanvas.getContext("2d"); - if (this.pixelRation === undefined) { - this.pixelRatio = (window.devicePixelRatio || 1) / (ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1); - } - ctx.setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0); - - // clear the canvas - var w = this.colorPickerCanvas.clientWidth; - var h = this.colorPickerCanvas.clientHeight; - ctx.clearRect(0, 0, w, h); - - - // draw hue circle - var x = undefined, - y = undefined, - hue = undefined, - sat = undefined; - this.centerCoordinates = { x: w * 0.5, y: h * 0.5 }; - this.r = 0.49 * w; - var angleConvert = 2 * Math.PI / 360; - var hfac = 1 / 360; - var sfac = 1 / this.r; - var rgb = undefined; - for (hue = 0; hue < 360; hue++) { - for (sat = 0; sat < this.r; sat++) { - x = this.centerCoordinates.x + sat * Math.sin(angleConvert * hue); - y = this.centerCoordinates.y + sat * Math.cos(angleConvert * hue); - rgb = util.HSVToRGB(hue * hfac, sat * sfac, 1); - ctx.fillStyle = "rgb(" + rgb.r + "," + rgb.g + "," + rgb.b + ")"; - ctx.fillRect(x - 0.5, y - 0.5, 2, 2); - } - } - ctx.strokeStyle = "rgba(0,0,0,1)"; - ctx.circle(this.centerCoordinates.x, this.centerCoordinates.y, this.r); - ctx.stroke(); + var _ShapeBase2 = __webpack_require__(106); - this.hueCircle = ctx.getImageData(0, 0, w, h); - } - this.generated = true; - }, - writable: true, - configurable: true - }, - _moveSelector: { + var _ShapeBase3 = _interopRequireWildcard(_ShapeBase2); + 'use strict'; - /** - * move the selector. This is called by hammer functions. - * - * @param event - * @private - */ - value: function _moveSelector(event) { - var rect = this.colorPickerDiv.getBoundingClientRect(); - var left = event.center.x - rect.left; - var top = event.center.y - rect.top; - - var centerY = 0.5 * this.colorPickerDiv.clientHeight; - var centerX = 0.5 * this.colorPickerDiv.clientWidth; - - var x = left - centerX; - var y = top - centerY; - - var angle = Math.atan2(x, y); - var radius = 0.98 * Math.min(Math.sqrt(x * x + y * y), centerX); - - var newTop = Math.cos(angle) * radius + centerY; - var newLeft = Math.sin(angle) * radius + centerX; - - this.colorPickerSelector.style.top = newTop - 0.5 * this.colorPickerSelector.clientHeight + "px"; - this.colorPickerSelector.style.left = newLeft - 0.5 * this.colorPickerSelector.clientWidth + "px"; - - // set color - var h = angle / (2 * Math.PI); - h = h < 0 ? h + 1 : h; - var s = radius / this.r; - var hsv = util.RGBToHSV(this.color.r, this.color.g, this.color.b); - hsv.h = h; - hsv.s = s; - var rgba = util.HSVToRGB(hsv.h, hsv.s, hsv.v); - rgba.a = this.color.a; - this.color = rgba; - - // update previews - this.initialColorDiv.style.backgroundColor = "rgba(" + this.initialColor.r + "," + this.initialColor.g + "," + this.initialColor.b + "," + this.initialColor.a + ")"; - this.newColorDiv.style.backgroundColor = "rgba(" + this.color.r + "," + this.color.g + "," + this.color.b + "," + this.color.a + ")"; - }, - writable: true, - configurable: true + var TriangleDown = (function (_ShapeBase) { + function TriangleDown(options, body, labelModule) { + _classCallCheck(this, TriangleDown); + + _get(Object.getPrototypeOf(TriangleDown.prototype), 'constructor', this).call(this, options, body, labelModule); + } + + _inherits(TriangleDown, _ShapeBase); + + _createClass(TriangleDown, [{ + key: 'resize', + value: function resize(ctx) { + this._resizeShape(); } - }); + }, { + key: 'draw', + value: function draw(ctx, x, y, selected, hover) { + this._drawShape(ctx, 'triangleDown', 3, x, y, selected, hover); + } + }, { + key: 'distanceToBorder', + value: function distanceToBorder(ctx, angle) { + return this._distanceToBorder(angle); + } + }]); - return ColorPicker; - })(); + return TriangleDown; + })(_ShapeBase3['default']); - module.exports = ColorPicker; + exports['default'] = TriangleDown; + module.exports = exports['default']; /***/ }, -/* 97 */ +/* 104 */ /***/ function(module, exports, __webpack_require__) { "use strict"; - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + Object.defineProperty(exports, "__esModule", { + value: true + }); + var NodeBase = (function () { function NodeBase(options, body, labelModule) { _classCallCheck(this, NodeBase); @@ -35097,256 +37268,215 @@ return /******/ (function(modules) { // webpackBootstrap this.boundingBox = { top: 0, left: 0, right: 0, bottom: 0 }; } - _prototypeProperties(NodeBase, null, { - setOptions: { - value: function setOptions(options) { - this.options = options; - }, - writable: true, - configurable: true - }, - _distanceToBorder: { - value: function _distanceToBorder(angle) { - var borderWidth = 1; - return Math.min(Math.abs(this.width / 2 / Math.cos(angle)), Math.abs(this.height / 2 / Math.sin(angle))) + borderWidth; - }, - writable: true, - configurable: true + _createClass(NodeBase, [{ + key: "setOptions", + value: function setOptions(options) { + this.options = options; } - }); + }, { + key: "_distanceToBorder", + value: function _distanceToBorder(angle) { + var borderWidth = 1; + return Math.min(Math.abs(this.width / 2 / Math.cos(angle)), Math.abs(this.height / 2 / Math.sin(angle))) + borderWidth; + } + }]); return NodeBase; })(); - module.exports = NodeBase; + exports["default"] = NodeBase; + module.exports = exports["default"]; /***/ }, -/* 98 */ +/* 105 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; - var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; - var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); - var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var _inherits = function (subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + + Object.defineProperty(exports, '__esModule', { + value: true + }); - var NodeBase = _interopRequire(__webpack_require__(97)); + var _NodeBase2 = __webpack_require__(104); - var CircleImageBase = (function (NodeBase) { + var _NodeBase3 = _interopRequireWildcard(_NodeBase2); + + var CircleImageBase = (function (_NodeBase) { function CircleImageBase(options, body, labelModule) { _classCallCheck(this, CircleImageBase); - _get(Object.getPrototypeOf(CircleImageBase.prototype), "constructor", this).call(this, options, body, labelModule); + _get(Object.getPrototypeOf(CircleImageBase.prototype), 'constructor', this).call(this, options, body, labelModule); } - _inherits(CircleImageBase, NodeBase); + _inherits(CircleImageBase, _NodeBase); - _prototypeProperties(CircleImageBase, null, { - _resizeImage: { - value: function _resizeImage() { - if (!this.width || !this.height) { - // undefined or 0 - var width, height, ratio; - if (this.imageObj.width && this.imageObj.height) { - // not undefined or 0 - width = 0; - height = 0; - } - if (this.imageObj.width > this.imageObj.height) { - ratio = this.imageObj.width / this.imageObj.height; - width = this.options.size * 2 * ratio || this.imageObj.width; - height = this.options.size * 2 || this.imageObj.height; - } else { - ratio = this.imageObj.height / this.imageObj.width; - width = this.options.size * 2 || this.imageObj.width; - height = this.options.size * 2 * ratio || this.imageObj.height; - } - this.width = width; - this.height = height; + _createClass(CircleImageBase, [{ + key: '_resizeImage', + value: function _resizeImage() { + if (!this.width || !this.height) { + // undefined or 0 + var width, height, ratio; + if (this.imageObj.width && this.imageObj.height) { + // not undefined or 0 + width = 0; + height = 0; } - }, - writable: true, - configurable: true - }, - _drawRawCircle: { - value: function _drawRawCircle(ctx, x, y, selected, hover, size) { - var borderWidth = this.options.borderWidth; - var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; + if (this.imageObj.width > this.imageObj.height) { + ratio = this.imageObj.width / this.imageObj.height; + width = this.options.size * 2 * ratio || this.imageObj.width; + height = this.options.size * 2 || this.imageObj.height; + } else { + ratio = this.imageObj.height / this.imageObj.width; + width = this.options.size * 2 || this.imageObj.width; + height = this.options.size * 2 * ratio || this.imageObj.height; + } + this.width = width; + this.height = height; + } + } + }, { + key: '_drawRawCircle', + value: function _drawRawCircle(ctx, x, y, selected, hover, size) { + var borderWidth = this.options.borderWidth; + var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; - ctx.strokeStyle = selected ? this.options.color.highlight.border : hover ? this.options.color.hover.border : this.options.color.border; + ctx.strokeStyle = selected ? this.options.color.highlight.border : hover ? this.options.color.hover.border : this.options.color.border; - ctx.lineWidth = selected ? selectionLineWidth : borderWidth; - ctx.lineWidth *= this.networkScaleInv; - ctx.lineWidth = Math.min(this.width, ctx.lineWidth); + ctx.lineWidth = selected ? selectionLineWidth : borderWidth; + ctx.lineWidth *= this.networkScaleInv; + ctx.lineWidth = Math.min(this.width, ctx.lineWidth); - ctx.fillStyle = selected ? this.options.color.highlight.background : hover ? this.options.color.hover.background : this.options.color.background; - ctx.circle(x, y, size); - ctx.fill(); - ctx.stroke(); - }, - writable: true, - configurable: true - }, - _drawImageAtPosition: { - value: function _drawImageAtPosition(ctx) { - if (this.imageObj.width != 0) { - // draw the image - ctx.globalAlpha = 1; - ctx.drawImage(this.imageObj, this.left, this.top, this.width, this.height); - } - }, - writable: true, - configurable: true - }, - _drawImageLabel: { - value: function _drawImageLabel(ctx, x, y, selected) { - var yLabel; - var offset = 0; - - if (this.height !== undefined) { - offset = this.height * 0.5; - var labelDimensions = this.labelModule.getTextSize(ctx); - if (labelDimensions.lineCount >= 1) { - offset += labelDimensions.height / 2; - } + ctx.fillStyle = selected ? this.options.color.highlight.background : hover ? this.options.color.hover.background : this.options.color.background; + ctx.circle(x, y, size); + ctx.fill(); + ctx.stroke(); + } + }, { + key: '_drawImageAtPosition', + value: function _drawImageAtPosition(ctx) { + if (this.imageObj.width != 0) { + // draw the image + ctx.globalAlpha = 1; + ctx.drawImage(this.imageObj, this.left, this.top, this.width, this.height); + } + } + }, { + key: '_drawImageLabel', + value: function _drawImageLabel(ctx, x, y, selected) { + var yLabel; + var offset = 0; + + if (this.height !== undefined) { + offset = this.height * 0.5; + var labelDimensions = this.labelModule.getTextSize(ctx); + if (labelDimensions.lineCount >= 1) { + offset += labelDimensions.height / 2; } + } - yLabel = y + offset; - this.labelModule.draw(ctx, x, yLabel, selected, "hanging"); - }, - writable: true, - configurable: true + yLabel = y + offset; + this.labelModule.draw(ctx, x, yLabel, selected, 'hanging'); } - }); + }]); return CircleImageBase; - })(NodeBase); + })(_NodeBase3['default']); - module.exports = CircleImageBase; + exports['default'] = CircleImageBase; + module.exports = exports['default']; /***/ }, -/* 99 */ +/* 106 */ /***/ function(module, exports, __webpack_require__) { - "use strict"; + 'use strict'; - var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; - var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; - var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); - var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + var _inherits = function (subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + + Object.defineProperty(exports, '__esModule', { + value: true + }); - var NodeBase = _interopRequire(__webpack_require__(97)); + var _NodeBase2 = __webpack_require__(104); - var ShapeBase = (function (NodeBase) { + var _NodeBase3 = _interopRequireWildcard(_NodeBase2); + + var ShapeBase = (function (_NodeBase) { function ShapeBase(options, body, labelModule) { _classCallCheck(this, ShapeBase); - _get(Object.getPrototypeOf(ShapeBase.prototype), "constructor", this).call(this, options, body, labelModule); + _get(Object.getPrototypeOf(ShapeBase.prototype), 'constructor', this).call(this, options, body, labelModule); } - _inherits(ShapeBase, NodeBase); - - _prototypeProperties(ShapeBase, null, { - _resizeShape: { - value: function _resizeShape() { - if (this.width === undefined) { - var size = 2 * this.options.size; - this.width = size; - this.height = size; - } - }, - writable: true, - configurable: true - }, - _drawShape: { - value: function _drawShape(ctx, shape, sizeMultiplier, x, y, selected, hover) { - this._resizeShape(); - - this.left = x - this.width / 2; - this.top = y - this.height / 2; - - var borderWidth = this.options.borderWidth; - var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; - - ctx.strokeStyle = selected ? this.options.color.highlight.border : hover ? this.options.color.hover.border : this.options.color.border; - ctx.lineWidth = selected ? selectionLineWidth : borderWidth; - ctx.lineWidth /= this.body.view.scale; - ctx.lineWidth = Math.min(this.width, ctx.lineWidth); - ctx.fillStyle = selected ? this.options.color.highlight.background : hover ? this.options.color.hover.background : this.options.color.background; - ctx[shape](x, y, this.options.size); - ctx.fill(); - ctx.stroke(); - - this.boundingBox.top = y - this.options.size; - this.boundingBox.left = x - this.options.size; - this.boundingBox.right = x + this.options.size; - this.boundingBox.bottom = y + this.options.size; + _inherits(ShapeBase, _NodeBase); - if (this.options.label !== undefined) { - var yLabel = y + 0.5 * this.height + 3; // the + 3 is to offset it a bit below the node. - this.labelModule.draw(ctx, x, yLabel, selected, "hanging"); - this.boundingBox.left = Math.min(this.boundingBox.left, this.labelModule.size.left); - this.boundingBox.right = Math.max(this.boundingBox.right, this.labelModule.size.left + this.labelModule.size.width); - this.boundingBox.bottom = Math.max(this.boundingBox.bottom, this.boundingBox.bottom + this.labelModule.size.height); - } - }, - writable: true, - configurable: true + _createClass(ShapeBase, [{ + key: '_resizeShape', + value: function _resizeShape() { + if (this.width === undefined) { + var size = 2 * this.options.size; + this.width = size; + this.height = size; + } } - }); + }, { + key: '_drawShape', + value: function _drawShape(ctx, shape, sizeMultiplier, x, y, selected, hover) { + this._resizeShape(); - return ShapeBase; - })(NodeBase); - - module.exports = ShapeBase; - -/***/ }, -/* 100 */ -/***/ function(module, exports, __webpack_require__) { - - "use strict"; + this.left = x - this.width / 2; + this.top = y - this.height / 2; - var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; - - var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - - var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; - - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; - - var Node = _interopRequire(__webpack_require__(80)); - - /** - * - */ - var Cluster = (function (Node) { - function Cluster(options, body, imagelist, grouplist, globalOptions) { - _classCallCheck(this, Cluster); + var borderWidth = this.options.borderWidth; + var selectionLineWidth = this.options.borderWidthSelected || 2 * this.options.borderWidth; - _get(Object.getPrototypeOf(Cluster.prototype), "constructor", this).call(this, options, body, imagelist, grouplist, globalOptions); + ctx.strokeStyle = selected ? this.options.color.highlight.border : hover ? this.options.color.hover.border : this.options.color.border; + ctx.lineWidth = selected ? selectionLineWidth : borderWidth; + ctx.lineWidth /= this.body.view.scale; + ctx.lineWidth = Math.min(this.width, ctx.lineWidth); + ctx.fillStyle = selected ? this.options.color.highlight.background : hover ? this.options.color.hover.background : this.options.color.background; + ctx[shape](x, y, this.options.size); + ctx.fill(); + ctx.stroke(); - this.isCluster = true; - this.containedNodes = {}; - this.containedEdges = {}; - } + this.boundingBox.top = y - this.options.size; + this.boundingBox.left = x - this.options.size; + this.boundingBox.right = x + this.options.size; + this.boundingBox.bottom = y + this.options.size; - _inherits(Cluster, Node); + if (this.options.label !== undefined) { + var yLabel = y + 0.5 * this.height + 3; // the + 3 is to offset it a bit below the node. + this.labelModule.draw(ctx, x, yLabel, selected, 'hanging'); + this.boundingBox.left = Math.min(this.boundingBox.left, this.labelModule.size.left); + this.boundingBox.right = Math.max(this.boundingBox.right, this.labelModule.size.left + this.labelModule.size.width); + this.boundingBox.bottom = Math.max(this.boundingBox.bottom, this.boundingBox.bottom + this.labelModule.size.height); + } + } + }]); - return Cluster; - })(Node); + return ShapeBase; + })(_NodeBase3['default']); - module.exports = Cluster; + exports['default'] = ShapeBase; + module.exports = exports['default']; /***/ } /******/ ]) diff --git a/examples/network/01_basic_usage.html b/examples/network/01_basic_usage.html index e6feac29..805bedff 100644 --- a/examples/network/01_basic_usage.html +++ b/examples/network/01_basic_usage.html @@ -11,14 +11,12 @@ width: 600px; height: 400px; border: 1px solid lightgray; - display:none; }
-