diff --git a/dist/vis.js b/dist/vis.js index dab6c25f..38f9ab09 100644 --- a/dist/vis.js +++ b/dist/vis.js @@ -15672,9 +15672,7 @@ return /******/ (function(modules) { // webpackBootstrap var _Validator2 = _interopRequireWildcard(_Validator); - var _allOptions = __webpack_require__(64); - - var _allOptions2 = _interopRequireWildcard(_allOptions); + var _allOptions$configureOptions = __webpack_require__(64); // Load custom shapes into CanvasRenderingContext2D __webpack_require__(65); @@ -15777,11 +15775,12 @@ return /******/ (function(modules) { // webpackBootstrap this.nodesHandler = new _NodesHandler2['default'](this.body, this.images, this.groups, this.layoutEngine); // Handle adding, deleting and updating of nodes as well as global options this.edgesHandler = new _EdgesHandler2['default'](this.body, this.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(); + // setup configuration system + this.configurationSystem = new _ConfigurationSystem2['default'](this, this.body.container, _allOptions$configureOptions.configureOptions, this.canvas.pixelRatio); + // apply options this.setOptions(options); @@ -15799,7 +15798,7 @@ return /******/ (function(modules) { // webpackBootstrap Network.prototype.setOptions = function (options) { if (options !== undefined) { - var errorFound = _Validator2['default'].validate(options, _allOptions2['default']); + var errorFound = _Validator2['default'].validate(options, _allOptions$configureOptions.allOptions); if (errorFound === true) { options = {}; console.log('%cErrors have been found in the supplied options object. None of the options will be used.', _Validator.printStyle); @@ -15821,7 +15820,21 @@ return /******/ (function(modules) { // webpackBootstrap this.clustering.setOptions(options.clustering); this.manipulation.setOptions(options.manipulation); - this.configurationSystem.setOptions(options); + this.configurationSystem.setOptions(options.configure); + + // if the configuration system is enabled, copy all options and put them into the config system + if (this.configurationSystem.options.enabled === true) { + var networkOptions = { nodes: {}, edges: {}, layout: {}, interaction: {}, manipulation: {}, physics: {}, selection: {}, rendering: {} }; + util.deepExtend(networkOptions.nodes, this.nodesHandler.options); + util.deepExtend(networkOptions.edges, this.edgesHandler.options); + util.deepExtend(networkOptions.layout, this.layoutEngine.options); + util.deepExtend(networkOptions.interaction, this.interactionHandler.options); + util.deepExtend(networkOptions.manipulation, this.manipulation.options); + util.deepExtend(networkOptions.physics, this.physics.options); + util.deepExtend(networkOptions.selection, this.selectionHandler.options); + util.deepExtend(networkOptions.rendering, this.renderer.options); + this.configurationSystem.setModuleOptions(networkOptions); + } // handle network global options if (options.clickToUse !== undefined) { @@ -25702,7 +25715,7 @@ return /******/ (function(modules) { // webpackBootstrap value: true }); - var _ColorPicker = __webpack_require__(83); + var _ColorPicker = __webpack_require__(109); var _ColorPicker2 = _interopRequireWildcard(_ColorPicker); @@ -25717,206 +25730,34 @@ return /******/ (function(modules) { // webpackBootstrap * * The options are matched with their counterparts in each of the modules and the values used in the configuration are * + * @param parentModule | the location where parentModule.setOptions() can be called + * @param defaultContainer | the default container of the module + * @param configureOptions | the fully configured and predefined options set found in allOptions.js + * @param pixelRatio | canvas pixel ratio */ var ConfigurationSystem = (function () { - function ConfigurationSystem(network) { + function ConfigurationSystem(parentModule, defaultContainer, configureOptions) { + var pixelRatio = arguments[3] === undefined ? 1 : arguments[3]; + _classCallCheck(this, ConfigurationSystem); - this.network = network; + this.parent = parentModule; this.changedOptions = []; + this.container = defaultContainer; - this.possibleOptions = { - nodes: { - borderWidth: [1, 0, 10, 1], - borderWidthSelected: [2, 0, 10, 1], - color: { - border: ['color', '#2B7CE9'], - background: ['color', '#97C2FC'], - highlight: { - border: ['color', '#2B7CE9'], - background: ['color', '#D2E5FF'] - }, - hover: { - border: ['color', '#2B7CE9'], - background: ['color', '#D2E5FF'] - } - }, - fixed: { - x: false, - y: false - }, - font: { - color: ['color', '#343434'], - size: [14, 0, 100, 1], // px - face: ['arial', 'verdana', 'tahoma'], - background: ['color', 'none'], - stroke: [0, 0, 50, 1], // px - strokeColor: ['color', '#ffffff'] - }, - //group: 'string', - hidden: false, - //icon: { - // face: 'string', //'FontAwesome', - // code: 'string', //'\uf007', - // size: [50, 0, 200, 1], //50, - // color: ['color','#2B7CE9'] //'#aa00ff' - //}, - //image: 'string', // --> URL - physics: true, - scaling: { - min: [10, 0, 200, 1], - max: [30, 0, 200, 1], - label: { - enabled: true, - min: [14, 0, 200, 1], - max: [30, 0, 200, 1], - maxVisible: [30, 0, 200, 1], - drawThreshold: [3, 0, 20, 1] - } - }, - shadow: { - enabled: false, - size: [10, 0, 20, 1], - x: [5, -30, 30, 1], - y: [5, -30, 30, 1] - }, - shape: ['ellipse', 'box', 'circle', 'database', 'diamond', 'dot', 'square', 'star', 'text', 'triangle', 'triangleDown'], - size: [25, 0, 200, 1] - }, - edges: { - arrows: { - to: { enabled: false, scaleFactor: [1, 0, 3, 0.05] }, // boolean / {arrowScaleFactor:1} / {enabled: false, arrowScaleFactor:1} - middle: { enabled: false, scaleFactor: [1, 0, 3, 0.05] }, - from: { enabled: false, scaleFactor: [1, 0, 3, 0.05] } - }, - color: { - color: ['color', '#848484'], - highlight: ['color', '#848484'], - hover: ['color', '#848484'], - inherit: ['from', 'to', 'both', true, false], - opacity: [1, 0, 1, 0.05] - }, - dashes: false, - font: { - color: ['color', '#343434'], - size: [14, 0, 100, 1], // px - face: ['arial', 'verdana', 'tahoma'], - background: ['color', 'none'], - stroke: [1, 0, 50, 1], // px - strokeColor: ['color', '#ffffff'], - align: ['horizontal', 'top', 'middle', 'bottom'] - }, - hidden: false, - hoverWidth: [2, 0, 5, 0.1], - physics: true, - scaling: { - min: [1, 0, 100, 1], - max: [15, 0, 100, 1], - label: { - enabled: true, - min: [14, 0, 200, 1], - max: [30, 0, 200, 1], - maxVisible: [30, 0, 200, 1], - drawThreshold: [3, 0, 20, 1] - } - }, - selectionWidth: [1.5, 0, 5, 0.1], - selfReferenceSize: [20, 0, 200, 1], - shadow: { - enabled: false, - size: [10, 0, 20, 1], - x: [5, -30, 30, 1], - y: [5, -30, 30, 1] - }, - smooth: { - enabled: true, - dynamic: true, - type: ['continuous', 'discrete', 'diagonalCross', 'straightCross', 'horizontal', 'vertical', 'curvedCW', 'curvedCCW'], - roundness: [0.5, 0, 1, 0.05] - }, - width: [1, 0, 30, 1] - }, - layout: { - randomSeed: [0, 0, 500, 1], - hierarchical: { - enabled: false, - levelSeparation: [150, 20, 500, 5], - direction: ['UD', 'DU', 'LR', 'RL'], // UD, DU, LR, RL - sortMethod: ['hubsize', 'directed'] // hubsize, directed - } - }, - interaction: { - dragNodes: true, - dragView: true, - zoomView: true, - hoverEnabled: false, - navigationButtons: false, - tooltipDelay: [300, 0, 1000, 25], - keyboard: { - enabled: false, - speed: { x: [10, 0, 40, 1], y: [10, 0, 40, 1], zoom: [0.02, 0, 0.1, 0.005] }, - bindToWindow: true - } - }, - manipulation: { - enabled: false, - initiallyActive: false, - locale: ['en', 'nl'] - }, - physics: { - barnesHut: { - //theta: [0.5, 0.1, 1, 0.05], - gravitationalConstant: [-2000, -30000, 0, 50], - centralGravity: [0.3, 0, 10, 0.05], - springLength: [95, 0, 500, 5], - springConstant: [0.04, 0, 5, 0.005], - damping: [0.09, 0, 1, 0.01] - }, - repulsion: { - centralGravity: [0.2, 0, 10, 0.05], - springLength: [200, 0, 500, 5], - springConstant: [0.05, 0, 5, 0.005], - nodeDistance: [100, 0, 500, 5], - damping: [0.09, 0, 1, 0.01] - }, - hierarchicalRepulsion: { - centralGravity: [0.2, 0, 10, 0.05], - springLength: [100, 0, 500, 5], - springConstant: [0.01, 0, 5, 0.005], - nodeDistance: [120, 0, 500, 5], - damping: [0.09, 0, 1, 0.01] - }, - maxVelocity: [50, 0, 150, 1], - minVelocity: [0.1, 0.01, 0.5, 0.01], - solver: ['barnesHut', 'repulsion', 'hierarchicalRepulsion'], - timestep: [0.5, 0, 1, 0.05] - }, - selection: { - selectable: true, - selectConnectedEdges: true - }, - rendering: { - hideEdgesOnDrag: false, - hideNodesOnDrag: false - } - }; - - this.actualOptions = { - nodes: {}, - edges: {}, - layout: {}, - interaction: {}, - manipulation: {}, - physics: {}, - selection: {}, - rendering: {}, - configure: false, - configureContainer: undefined + this.options = {}; + this.defaultOptions = { + enabled: false, + filter: true, + container: undefined }; + util.extend(this.options, this.defaultOptions); + this.configureOptions = configureOptions; + this.moduleOptions = {}; this.domElements = []; - this.colorPicker = new _ColorPicker2['default'](this.network.canvas.pixelRatio); + this.colorPicker = new _ColorPicker2['default'](pixelRatio); this.wrapper; } @@ -25931,41 +25772,39 @@ return /******/ (function(modules) { // webpackBootstrap */ value: function setOptions(options) { if (options !== undefined) { - util.extend(this.actualOptions, options); - } - - 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.rendering, this.network.renderer.selection, true); - - this.container = this.network.body.container; - var config = true; - if (typeof this.actualOptions.configure === 'string') { - config = this.actualOptions.configure; - } else if (this.actualOptions.configure instanceof Array) { - config = this.actualOptions.configure.join(); - } else if (typeof this.actualOptions.configure === 'object') { - if (this.actualOptions.configure.container !== undefined) { - this.container = this.actualOptions.configure.container; + var enabled = true; + if (typeof options === 'string') { + this.options.filter = options; + } else if (options instanceof Array) { + this.options.filter = options.join(); + } else if (typeof options === 'object') { + if (options.container !== undefined) { + this.options.container = options.container; } - if (this.actualOptions.configure.filter !== undefined) { - config = this.actualOptions.configure.filter; + if (options.filter !== undefined) { + this.options.filter = options.filter; } - } else if (typeof this.actualOptions.configure === 'boolean') { - config = this.actualOptions.configure; + if (options.enabled !== undefined) { + enabled = options.enabled; + } + } else if (typeof options === 'boolean') { + this.options.filter = true; + enabled = options; } - - if (config !== false) { - this._create(config); + this.options.enabled = enabled; + } + this._clean(); + } + }, { + key: 'setModuleOptions', + value: function setModuleOptions(moduleOptions) { + this.moduleOptions = moduleOptions; + if (this.options.enabled === true) { + this._clean(); + if (this.options.container !== undefined) { + this.container = this.options.container; } + this._create(this.options.filter); } } }, { @@ -25983,10 +25822,10 @@ return /******/ (function(modules) { // webpackBootstrap this.changedOptions = []; var counter = 0; - for (var option in this.possibleOptions) { - if (this.possibleOptions.hasOwnProperty(option)) { + for (var option in this.configureOptions) { + if (this.configureOptions.hasOwnProperty(option)) { if (config === true || config.indexOf(option) !== -1) { - var optionObj = this.possibleOptions[option]; + var optionObj = this.configureOptions[option]; // linebreak between categories if (counter > 0) { @@ -26067,7 +25906,7 @@ return /******/ (function(modules) { // webpackBootstrap * @private */ value: function _getValue(path) { - var base = this.actualOptions; + var base = this.moduleOptions; for (var i = 0; i < path.length; i++) { if (base[path[i]] !== undefined) { base = base[path[i]]; @@ -26078,24 +25917,6 @@ return /******/ (function(modules) { // webpackBootstrap } 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; - } }, { key: '_makeItem', @@ -26363,7 +26184,7 @@ return /******/ (function(modules) { // webpackBootstrap // collapse the physics options that are not enabled var draw = true; if (path.indexOf('physics') !== -1) { - if (this.actualOptions.physics.solver !== subObj) { + if (this.moduleOptions.physics.solver !== subObj) { draw = false; } } @@ -26432,7 +26253,7 @@ return /******/ (function(modules) { // webpackBootstrap */ value: function _update(value, path) { var options = this._constructOptions(value, path); - this.network.setOptions(options); + this.parent.setOptions(options); } }, { key: '_constructOptions', @@ -26455,7 +26276,6 @@ return /******/ (function(modules) { // webpackBootstrap pointer[path[i]] = value; } } - console.log(optionsObj); return optionsObj; } }, { @@ -26785,9 +26605,10 @@ return /******/ (function(modules) { // webpackBootstrap }, clustering: {}, configure: { + enabled: { boolean: boolean }, filter: { boolean: boolean, string: ['nodes', 'edges', 'layout', 'physics', 'manipulation', 'interaction', 'selection', 'rendering'], array: array }, container: { dom: dom }, - __type__: { object: object, string: string, array: array, boolean: boolean } + __type__: { object: object, boolean: boolean, string: ['nodes', 'edges', 'layout', 'physics', 'manipulation', 'interaction', 'selection', 'rendering'], array: array } }, edges: { arrows: { @@ -27032,8 +26853,184 @@ return /******/ (function(modules) { // webpackBootstrap allOptions.groups.__any__ = allOptions.nodes; allOptions.manipulation.controlNodeStyle = allOptions.nodes; - exports['default'] = allOptions; - module.exports = exports['default']; + var configureOptions = { + nodes: { + borderWidth: [1, 0, 10, 1], + borderWidthSelected: [2, 0, 10, 1], + color: { + border: ['color', '#2B7CE9'], + background: ['color', '#97C2FC'], + highlight: { + border: ['color', '#2B7CE9'], + background: ['color', '#D2E5FF'] + }, + hover: { + border: ['color', '#2B7CE9'], + background: ['color', '#D2E5FF'] + } + }, + fixed: { + x: false, + y: false + }, + font: { + color: ['color', '#343434'], + size: [14, 0, 100, 1], // px + face: ['arial', 'verdana', 'tahoma'], + background: ['color', 'none'], + stroke: [0, 0, 50, 1], // px + strokeColor: ['color', '#ffffff'] + }, + //group: 'string', + hidden: false, + //icon: { + // face: 'string', //'FontAwesome', + // code: 'string', //'\uf007', + // size: [50, 0, 200, 1], //50, + // color: ['color','#2B7CE9'] //'#aa00ff' + //}, + //image: 'string', // --> URL + physics: true, + scaling: { + min: [10, 0, 200, 1], + max: [30, 0, 200, 1], + label: { + enabled: true, + min: [14, 0, 200, 1], + max: [30, 0, 200, 1], + maxVisible: [30, 0, 200, 1], + drawThreshold: [3, 0, 20, 1] + } + }, + shadow: { + enabled: false, + size: [10, 0, 20, 1], + x: [5, -30, 30, 1], + y: [5, -30, 30, 1] + }, + shape: ['ellipse', 'box', 'circle', 'database', 'diamond', 'dot', 'square', 'star', 'text', 'triangle', 'triangleDown'], + size: [25, 0, 200, 1] + }, + edges: { + arrows: { + to: { enabled: false, scaleFactor: [1, 0, 3, 0.05] }, // boolean / {arrowScaleFactor:1} / {enabled: false, arrowScaleFactor:1} + middle: { enabled: false, scaleFactor: [1, 0, 3, 0.05] }, + from: { enabled: false, scaleFactor: [1, 0, 3, 0.05] } + }, + color: { + color: ['color', '#848484'], + highlight: ['color', '#848484'], + hover: ['color', '#848484'], + inherit: ['from', 'to', 'both', true, false], + opacity: [1, 0, 1, 0.05] + }, + dashes: false, + font: { + color: ['color', '#343434'], + size: [14, 0, 100, 1], // px + face: ['arial', 'verdana', 'tahoma'], + background: ['color', 'none'], + stroke: [1, 0, 50, 1], // px + strokeColor: ['color', '#ffffff'], + align: ['horizontal', 'top', 'middle', 'bottom'] + }, + hidden: false, + hoverWidth: [2, 0, 5, 0.1], + physics: true, + scaling: { + min: [1, 0, 100, 1], + max: [15, 0, 100, 1], + label: { + enabled: true, + min: [14, 0, 200, 1], + max: [30, 0, 200, 1], + maxVisible: [30, 0, 200, 1], + drawThreshold: [3, 0, 20, 1] + } + }, + selectionWidth: [1.5, 0, 5, 0.1], + selfReferenceSize: [20, 0, 200, 1], + shadow: { + enabled: false, + size: [10, 0, 20, 1], + x: [5, -30, 30, 1], + y: [5, -30, 30, 1] + }, + smooth: { + enabled: true, + dynamic: true, + type: ['continuous', 'discrete', 'diagonalCross', 'straightCross', 'horizontal', 'vertical', 'curvedCW', 'curvedCCW'], + roundness: [0.5, 0, 1, 0.05] + }, + width: [1, 0, 30, 1] + }, + layout: { + randomSeed: [0, 0, 500, 1], + hierarchical: { + enabled: false, + levelSeparation: [150, 20, 500, 5], + direction: ['UD', 'DU', 'LR', 'RL'], // UD, DU, LR, RL + sortMethod: ['hubsize', 'directed'] // hubsize, directed + } + }, + interaction: { + dragNodes: true, + dragView: true, + zoomView: true, + hoverEnabled: false, + navigationButtons: false, + tooltipDelay: [300, 0, 1000, 25], + keyboard: { + enabled: false, + speed: { x: [10, 0, 40, 1], y: [10, 0, 40, 1], zoom: [0.02, 0, 0.1, 0.005] }, + bindToWindow: true + } + }, + manipulation: { + enabled: false, + initiallyActive: false, + locale: ['en', 'nl'] + }, + physics: { + barnesHut: { + //theta: [0.5, 0.1, 1, 0.05], + gravitationalConstant: [-2000, -30000, 0, 50], + centralGravity: [0.3, 0, 10, 0.05], + springLength: [95, 0, 500, 5], + springConstant: [0.04, 0, 5, 0.005], + damping: [0.09, 0, 1, 0.01] + }, + repulsion: { + centralGravity: [0.2, 0, 10, 0.05], + springLength: [200, 0, 500, 5], + springConstant: [0.05, 0, 5, 0.005], + nodeDistance: [100, 0, 500, 5], + damping: [0.09, 0, 1, 0.01] + }, + hierarchicalRepulsion: { + centralGravity: [0.2, 0, 10, 0.05], + springLength: [100, 0, 500, 5], + springConstant: [0.01, 0, 5, 0.005], + nodeDistance: [120, 0, 500, 5], + damping: [0.09, 0, 1, 0.01] + }, + maxVelocity: [50, 0, 150, 1], + minVelocity: [0.1, 0.01, 0.5, 0.01], + solver: ['barnesHut', 'repulsion', 'hierarchicalRepulsion'], + timestep: [0.5, 0, 1, 0.05] + }, + selection: { + selectable: true, + selectConnectedEdges: true + }, + rendering: { + hideEdgesOnDrag: false, + hideNodesOnDrag: false + } + }; + + exports.allOptions = allOptions; + exports.configureOptions = configureOptions; /***/ }, /* 65 */ @@ -27325,7 +27322,7 @@ return /******/ (function(modules) { // webpackBootstrap 'use strict'; - var keycharm = __webpack_require__(84); + var keycharm = __webpack_require__(83); var Emitter = __webpack_require__(43); var Hammer = __webpack_require__(41); var util = __webpack_require__(1); @@ -30559,7 +30556,7 @@ return /******/ (function(modules) { // webpackBootstrap return _moment; })); - /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(86)(module))) + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(85)(module))) /***/ }, /* 68 */ @@ -33245,7 +33242,7 @@ return /******/ (function(modules) { // webpackBootstrap prefixed: prefixed }); - if ("function" == TYPE_FUNCTION && __webpack_require__(87)) { + if ("function" == TYPE_FUNCTION && __webpack_require__(86)) { !(__WEBPACK_AMD_DEFINE_RESULT__ = function() { return Hammer; }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); @@ -33278,59 +33275,59 @@ return /******/ (function(modules) { // webpackBootstrap var _Label2 = _interopRequireWildcard(_Label); - var _Box = __webpack_require__(88); + var _Box = __webpack_require__(87); var _Box2 = _interopRequireWildcard(_Box); - var _Circle = __webpack_require__(89); + var _Circle = __webpack_require__(88); var _Circle2 = _interopRequireWildcard(_Circle); - var _CircularImage = __webpack_require__(90); + var _CircularImage = __webpack_require__(89); var _CircularImage2 = _interopRequireWildcard(_CircularImage); - var _Database = __webpack_require__(91); + var _Database = __webpack_require__(90); var _Database2 = _interopRequireWildcard(_Database); - var _Diamond = __webpack_require__(92); + var _Diamond = __webpack_require__(91); var _Diamond2 = _interopRequireWildcard(_Diamond); - var _Dot = __webpack_require__(93); + var _Dot = __webpack_require__(92); var _Dot2 = _interopRequireWildcard(_Dot); - var _Ellipse = __webpack_require__(94); + var _Ellipse = __webpack_require__(93); var _Ellipse2 = _interopRequireWildcard(_Ellipse); - var _Icon = __webpack_require__(95); + var _Icon = __webpack_require__(94); var _Icon2 = _interopRequireWildcard(_Icon); - var _Image = __webpack_require__(96); + var _Image = __webpack_require__(95); var _Image2 = _interopRequireWildcard(_Image); - var _Square = __webpack_require__(97); + var _Square = __webpack_require__(96); var _Square2 = _interopRequireWildcard(_Square); - var _Star = __webpack_require__(98); + var _Star = __webpack_require__(97); var _Star2 = _interopRequireWildcard(_Star); - var _Text = __webpack_require__(99); + var _Text = __webpack_require__(98); var _Text2 = _interopRequireWildcard(_Text); - var _Triangle = __webpack_require__(100); + var _Triangle = __webpack_require__(99); var _Triangle2 = _interopRequireWildcard(_Triangle); - var _TriangleDown = __webpack_require__(101); + var _TriangleDown = __webpack_require__(100); var _TriangleDown2 = _interopRequireWildcard(_TriangleDown); @@ -34064,15 +34061,15 @@ return /******/ (function(modules) { // webpackBootstrap var _Label2 = _interopRequireWildcard(_Label); - var _BezierEdgeDynamic = __webpack_require__(102); + var _BezierEdgeDynamic = __webpack_require__(101); var _BezierEdgeDynamic2 = _interopRequireWildcard(_BezierEdgeDynamic); - var _BezierEdgeStatic = __webpack_require__(103); + var _BezierEdgeStatic = __webpack_require__(102); var _BezierEdgeStatic2 = _interopRequireWildcard(_BezierEdgeStatic); - var _StraightEdge = __webpack_require__(104); + var _StraightEdge = __webpack_require__(103); var _StraightEdge2 = _interopRequireWildcard(_StraightEdge); @@ -35594,7 +35591,7 @@ return /******/ (function(modules) { // webpackBootstrap var util = __webpack_require__(1); var Hammer = __webpack_require__(41); var hammerUtil = __webpack_require__(45); - var keycharm = __webpack_require__(84); + var keycharm = __webpack_require__(83); var NavigationHandler = (function () { function NavigationHandler(body, canvas) { @@ -36019,676 +36016,97 @@ return /******/ (function(modules) { // webpackBootstrap /* 83 */ /***/ function(module, exports, __webpack_require__) { - 'use strict'; + var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;"use strict"; + /** + * Created by Alex on 11/6/2014. + */ - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; + // 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 () { - var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + function keycharm(options) { + var preventDefault = options && options.preventDefault || false; - Object.defineProperty(exports, '__esModule', { - value: true - }); - var Hammer = __webpack_require__(41); - var hammerUtil = __webpack_require__(45); - var util = __webpack_require__(1); + var container = options && options.container || window; + var _exportFunctions = {}; + var _bound = {keydown:{}, keyup:{}}; + var _keys = {}; + var i; - var ColorPicker = (function () { - function ColorPicker() { - var pixelRatio = arguments[0] === undefined ? 1 : arguments[0]; + // a - z + for (i = 97; i <= 122; i++) {_keys[String.fromCharCode(i)] = {code:65 + (i - 97), shift: false};} + // A - Z + for (i = 65; i <= 90; i++) {_keys[String.fromCharCode(i)] = {code:i, shift: true};} + // 0 - 9 + for (i = 0; i <= 9; i++) {_keys['' + i] = {code:48 + i, shift: false};} + // F1 - F12 + for (i = 1; i <= 12; i++) {_keys['F' + i] = {code:111 + i, shift: false};} + // num0 - num9 + for (i = 0; i <= 9; i++) {_keys['num' + i] = {code:96 + i, shift: false};} - _classCallCheck(this, ColorPicker); + // numpad misc + _keys['num*'] = {code:106, shift: false}; + _keys['num+'] = {code:107, shift: false}; + _keys['num-'] = {code:109, shift: false}; + _keys['num/'] = {code:111, shift: false}; + _keys['num.'] = {code:110, shift: false}; + // arrows + _keys['left'] = {code:37, shift: false}; + _keys['up'] = {code:38, shift: false}; + _keys['right'] = {code:39, shift: false}; + _keys['down'] = {code:40, shift: false}; + // extra keys + _keys['space'] = {code:32, shift: false}; + _keys['enter'] = {code:13, shift: false}; + _keys['shift'] = {code:16, shift: undefined}; + _keys['esc'] = {code:27, shift: false}; + _keys['backspace'] = {code:8, shift: false}; + _keys['tab'] = {code:9, shift: false}; + _keys['ctrl'] = {code:17, shift: false}; + _keys['alt'] = {code:18, shift: false}; + _keys['delete'] = {code:46, shift: false}; + _keys['pageup'] = {code:33, shift: false}; + _keys['pagedown'] = {code:34, shift: false}; + // symbols + _keys['='] = {code:187, shift: false}; + _keys['-'] = {code:189, shift: false}; + _keys[']'] = {code:221, shift: false}; + _keys['['] = {code:219, shift: false}; - this.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(); - } + var down = function(event) {handleEvent(event,'keydown');}; + var up = function(event) {handleEvent(event,'keyup');}; - _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() { - this.frame = document.createElement('div'); - this.frame.className = 'vis-color-picker'; - - this.colorPickerDiv = document.createElement('div'); - this.colorPickerSelector = document.createElement('div'); - this.colorPickerSelector.className = 'vis-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 = 'vis-color'; - - this.opacityDiv = document.createElement('div'); - this.opacityDiv.className = 'vis-opacity'; - - this.brightnessDiv = document.createElement('div'); - this.brightnessDiv.className = 'vis-brightness'; - - this.arrowDiv = document.createElement('div'); - this.arrowDiv.className = 'vis-arrow'; - - this.opacityRange = document.createElement('input'); - this.opacityRange.type = 'range'; - this.opacityRange.min = '0'; - this.opacityRange.max = '100'; - this.opacityRange.value = '100'; - this.opacityRange.className = 'vis-range'; - - this.brightnessRange = document.createElement('input'); - this.brightnessRange.type = 'range'; - this.brightnessRange.min = '0'; - this.brightnessRange.max = '100'; - this.brightnessRange.value = '100'; - this.brightnessRange.className = 'vis-range'; - - 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 = 'vis-label vis-brightness'; - this.brightnessLabel.innerHTML = 'brightness:'; - - this.opacityLabel = document.createElement('div'); - this.opacityLabel.className = 'vis-label vis-opacity'; - this.opacityLabel.innerHTML = 'opacity:'; - - this.newColorDiv = document.createElement('div'); - this.newColorDiv.className = 'vis-new-color'; - this.newColorDiv.innerHTML = 'new'; - - this.initialColorDiv = document.createElement('div'); - this.initialColorDiv.className = 'vis-initial-color'; - this.initialColorDiv.innerHTML = 'initial'; - - this.cancelButton = document.createElement('div'); - this.cancelButton.className = 'vis-button vis-cancel'; - this.cancelButton.innerHTML = 'cancel'; - this.cancelButton.onclick = this._hide.bind(this, false); - - this.applyButton = document.createElement('div'); - this.applyButton.className = 'vis-button vis-apply'; - this.applyButton.innerHTML = 'apply'; - this.applyButton.onclick = this._apply.bind(this); - - this.saveButton = document.createElement('div'); - this.saveButton.className = 'vis-button vis-save'; - this.saveButton.innerHTML = 'save'; - this.saveButton.onclick = this._save.bind(this); - - this.loadButton = document.createElement('div'); - this.loadButton.className = 'vis-button vis-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', - - /** - * 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(); - - this.hueCircle = ctx.getImageData(0, 0, w, h); - } - this.generated = true; - } - }, { - key: '_moveSelector', - - /** - * 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 + ')'; - } - }]); - - return ColorPicker; - })(); - - exports['default'] = ColorPicker; - module.exports = exports['default']; - -/***/ }, -/* 84 */ -/***/ function(module, exports, __webpack_require__) { - - var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;"use strict"; - /** - * Created by Alex on 11/6/2014. - */ - - // https://github.com/umdjs/umd/blob/master/returnExports.js#L40-L60 - // if the module has no dependencies, the above pattern can be simplified to - (function (root, factory) { - if (true) { - // AMD. Register as an anonymous module. - !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); - } else if (typeof exports === 'object') { - // Node. Does not work with strict CommonJS, but - // only CommonJS-like environments that support module.exports, - // like Node. - module.exports = factory(); - } else { - // Browser globals (root is window) - root.keycharm = factory(); - } - }(this, function () { - - function keycharm(options) { - var preventDefault = options && options.preventDefault || false; - - var container = options && options.container || window; - var _exportFunctions = {}; - var _bound = {keydown:{}, keyup:{}}; - var _keys = {}; - var i; - - // a - z - for (i = 97; i <= 122; i++) {_keys[String.fromCharCode(i)] = {code:65 + (i - 97), shift: false};} - // A - Z - for (i = 65; i <= 90; i++) {_keys[String.fromCharCode(i)] = {code:i, shift: true};} - // 0 - 9 - for (i = 0; i <= 9; i++) {_keys['' + i] = {code:48 + i, shift: false};} - // F1 - F12 - for (i = 1; i <= 12; i++) {_keys['F' + i] = {code:111 + i, shift: false};} - // num0 - num9 - for (i = 0; i <= 9; i++) {_keys['num' + i] = {code:96 + i, shift: false};} - - // numpad misc - _keys['num*'] = {code:106, shift: false}; - _keys['num+'] = {code:107, shift: false}; - _keys['num-'] = {code:109, shift: false}; - _keys['num/'] = {code:111, shift: false}; - _keys['num.'] = {code:110, shift: false}; - // arrows - _keys['left'] = {code:37, shift: false}; - _keys['up'] = {code:38, shift: false}; - _keys['right'] = {code:39, shift: false}; - _keys['down'] = {code:40, shift: false}; - // extra keys - _keys['space'] = {code:32, shift: false}; - _keys['enter'] = {code:13, shift: false}; - _keys['shift'] = {code:16, shift: undefined}; - _keys['esc'] = {code:27, shift: false}; - _keys['backspace'] = {code:8, shift: false}; - _keys['tab'] = {code:9, shift: false}; - _keys['ctrl'] = {code:17, shift: false}; - _keys['alt'] = {code:18, shift: false}; - _keys['delete'] = {code:46, shift: false}; - _keys['pageup'] = {code:33, shift: false}; - _keys['pagedown'] = {code:34, shift: false}; - // symbols - _keys['='] = {code:187, shift: false}; - _keys['-'] = {code:189, shift: false}; - _keys[']'] = {code:221, shift: false}; - _keys['['] = {code:219, shift: false}; - - - - var down = function(event) {handleEvent(event,'keydown');}; - var up = function(event) {handleEvent(event,'keyup');}; - - // handle the actualy bound key with the event - var handleEvent = function(event,type) { - if (_bound[type][event.keyCode] !== undefined) { - var bound = _bound[type][event.keyCode]; - for (var i = 0; i < bound.length; i++) { - if (bound[i].shift === undefined) { - bound[i].fn(event); - } - else if (bound[i].shift == true && event.shiftKey == true) { - bound[i].fn(event); - } - else if (bound[i].shift == false && event.shiftKey == false) { - bound[i].fn(event); - } - } + // handle the actualy bound key with the event + var handleEvent = function(event,type) { + if (_bound[type][event.keyCode] !== undefined) { + var bound = _bound[type][event.keyCode]; + for (var i = 0; i < bound.length; i++) { + if (bound[i].shift === undefined) { + bound[i].fn(event); + } + else if (bound[i].shift == true && event.shiftKey == true) { + bound[i].fn(event); + } + else if (bound[i].shift == false && event.shiftKey == false) { + bound[i].fn(event); + } + } if (preventDefault == true) { event.preventDefault(); @@ -36793,7 +36211,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 85 */ +/* 84 */ /***/ function(module, exports, __webpack_require__) { function webpackContext(req) { @@ -36802,11 +36220,11 @@ return /******/ (function(modules) { // webpackBootstrap webpackContext.keys = function() { return []; }; webpackContext.resolve = webpackContext; module.exports = webpackContext; - webpackContext.id = 85; + webpackContext.id = 84; /***/ }, -/* 86 */ +/* 85 */ /***/ function(module, exports, __webpack_require__) { module.exports = function(module) { @@ -36822,7 +36240,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }, -/* 87 */ +/* 86 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(__webpack_amd_options__) {module.exports = __webpack_amd_options__; @@ -36830,7 +36248,7 @@ return /******/ (function(modules) { // webpackBootstrap /* WEBPACK VAR INJECTION */}.call(exports, {})) /***/ }, -/* 88 */ +/* 87 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -36849,7 +36267,7 @@ return /******/ (function(modules) { // webpackBootstrap value: true }); - var _NodeBase2 = __webpack_require__(105); + var _NodeBase2 = __webpack_require__(104); var _NodeBase3 = _interopRequireWildcard(_NodeBase2); @@ -36928,7 +36346,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 89 */ +/* 88 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -36947,7 +36365,7 @@ return /******/ (function(modules) { // webpackBootstrap value: true }); - var _CircleImageBase2 = __webpack_require__(106); + var _CircleImageBase2 = __webpack_require__(105); var _CircleImageBase3 = _interopRequireWildcard(_CircleImageBase2); @@ -37010,7 +36428,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 90 */ +/* 89 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -37029,7 +36447,7 @@ return /******/ (function(modules) { // webpackBootstrap value: true }); - var _CircleImageBase2 = __webpack_require__(106); + var _CircleImageBase2 = __webpack_require__(105); var _CircleImageBase3 = _interopRequireWildcard(_CircleImageBase2); @@ -37111,7 +36529,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 91 */ +/* 90 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -37130,7 +36548,7 @@ return /******/ (function(modules) { // webpackBootstrap value: true }); - var _NodeBase2 = __webpack_require__(105); + var _NodeBase2 = __webpack_require__(104); var _NodeBase3 = _interopRequireWildcard(_NodeBase2); @@ -37209,7 +36627,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 92 */ +/* 91 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -37228,7 +36646,7 @@ return /******/ (function(modules) { // webpackBootstrap value: true }); - var _ShapeBase2 = __webpack_require__(107); + var _ShapeBase2 = __webpack_require__(106); var _ShapeBase3 = _interopRequireWildcard(_ShapeBase2); @@ -37267,7 +36685,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 93 */ +/* 92 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -37286,7 +36704,7 @@ return /******/ (function(modules) { // webpackBootstrap value: true }); - var _ShapeBase2 = __webpack_require__(107); + var _ShapeBase2 = __webpack_require__(106); var _ShapeBase3 = _interopRequireWildcard(_ShapeBase2); @@ -37325,7 +36743,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 94 */ +/* 93 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -37344,7 +36762,7 @@ return /******/ (function(modules) { // webpackBootstrap value: true }); - var _NodeBase2 = __webpack_require__(105); + var _NodeBase2 = __webpack_require__(104); var _NodeBase3 = _interopRequireWildcard(_NodeBase2); @@ -37426,7 +36844,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 95 */ +/* 94 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -37445,7 +36863,7 @@ return /******/ (function(modules) { // webpackBootstrap value: true }); - var _NodeBase2 = __webpack_require__(105); + var _NodeBase2 = __webpack_require__(104); var _NodeBase3 = _interopRequireWildcard(_NodeBase2); @@ -37534,7 +36952,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 96 */ +/* 95 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -37553,7 +36971,7 @@ return /******/ (function(modules) { // webpackBootstrap value: true }); - var _CircleImageBase2 = __webpack_require__(106); + var _CircleImageBase2 = __webpack_require__(105); var _CircleImageBase3 = _interopRequireWildcard(_CircleImageBase2); @@ -37612,7 +37030,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 97 */ +/* 96 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -37631,7 +37049,7 @@ return /******/ (function(modules) { // webpackBootstrap value: true }); - var _ShapeBase2 = __webpack_require__(107); + var _ShapeBase2 = __webpack_require__(106); var _ShapeBase3 = _interopRequireWildcard(_ShapeBase2); @@ -37671,7 +37089,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 98 */ +/* 97 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -37690,7 +37108,7 @@ return /******/ (function(modules) { // webpackBootstrap value: true }); - var _ShapeBase2 = __webpack_require__(107); + var _ShapeBase2 = __webpack_require__(106); var _ShapeBase3 = _interopRequireWildcard(_ShapeBase2); @@ -37729,7 +37147,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 99 */ +/* 98 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -37748,7 +37166,7 @@ return /******/ (function(modules) { // webpackBootstrap value: true }); - var _NodeBase2 = __webpack_require__(105); + var _NodeBase2 = __webpack_require__(104); var _NodeBase3 = _interopRequireWildcard(_NodeBase2); @@ -37807,7 +37225,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 100 */ +/* 99 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -37826,7 +37244,7 @@ return /******/ (function(modules) { // webpackBootstrap value: true }); - var _ShapeBase2 = __webpack_require__(107); + var _ShapeBase2 = __webpack_require__(106); var _ShapeBase3 = _interopRequireWildcard(_ShapeBase2); @@ -37865,7 +37283,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 101 */ +/* 100 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -37884,7 +37302,7 @@ return /******/ (function(modules) { // webpackBootstrap value: true }); - var _ShapeBase2 = __webpack_require__(107); + var _ShapeBase2 = __webpack_require__(106); var _ShapeBase3 = _interopRequireWildcard(_ShapeBase2); @@ -37923,7 +37341,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 102 */ +/* 101 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -37942,7 +37360,7 @@ return /******/ (function(modules) { // webpackBootstrap value: true }); - var _BezierEdgeBase2 = __webpack_require__(108); + var _BezierEdgeBase2 = __webpack_require__(107); var _BezierEdgeBase3 = _interopRequireWildcard(_BezierEdgeBase2); @@ -38079,7 +37497,7 @@ return /******/ (function(modules) { // webpackBootstrap module.exports = exports['default']; /***/ }, -/* 103 */ +/* 102 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -38098,7 +37516,7 @@ return /******/ (function(modules) { // webpackBootstrap value: true }); - var _BezierEdgeBase2 = __webpack_require__(108); + var _BezierEdgeBase2 = __webpack_require__(107); var _BezierEdgeBase3 = _interopRequireWildcard(_BezierEdgeBase2); @@ -38299,51 +37717,348 @@ return /******/ (function(modules) { // webpackBootstrap } } } - return { x: xVia, y: yVia }; + return { x: xVia, y: yVia }; + } + }, { + key: '_findBorderPosition', + value: function _findBorderPosition(nearNode, ctx) { + var options = arguments[2] === undefined ? {} : arguments[2]; + + 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', + + /** + * 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]; + + 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; + + return { x: x, y: y }; + } + }]); + + return BezierEdgeStatic; + })(_BezierEdgeBase3['default']); + + exports['default'] = BezierEdgeStatic; + module.exports = exports['default']; + +/***/ }, +/* 103 */ +/***/ 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; }; })(); + + 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 _EdgeBase2 = __webpack_require__(108); + + var _EdgeBase3 = _interopRequireWildcard(_EdgeBase2); + + var StraightEdge = (function (_EdgeBase) { + function StraightEdge(options, body, labelModule) { + _classCallCheck(this, StraightEdge); + + _get(Object.getPrototypeOf(StraightEdge.prototype), 'constructor', this).call(this, options, body, labelModule); + } + + _inherits(StraightEdge, _EdgeBase); + + _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); + // draw shadow if enabled + this.enableShadow(ctx); + ctx.stroke(); + this.disableShadow(ctx); + return undefined; + } + }, { + 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) { + 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; + + var borderPos = {}; + borderPos.x = (1 - toBorderPoint) * node2.x + toBorderPoint * node1.x; + borderPos.y = (1 - toBorderPoint) * node2.y + toBorderPoint * node1.y; + + 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 StraightEdge; + })(_EdgeBase3['default']); + + exports['default'] = StraightEdge; + module.exports = exports['default']; + +/***/ }, +/* 104 */ +/***/ 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 NodeBase = (function () { + function NodeBase(options, body, labelModule) { + _classCallCheck(this, NodeBase); + + this.body = body; + this.labelModule = labelModule; + this.setOptions(options); + this.top = undefined; + this.left = undefined; + this.height = undefined; + this.boundingBox = { top: 0, left: 0, right: 0, bottom: 0 }; + } + + _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; + } + }, { + key: 'enableShadow', + value: function enableShadow(ctx) { + if (this.options.shadow.enabled === true) { + ctx.shadowColor = 'rgba(0,0,0,0.5)'; + ctx.shadowBlur = this.options.shadow.size; + ctx.shadowOffsetX = this.options.shadow.x; + ctx.shadowOffsetY = this.options.shadow.y; + } + } + }, { + key: 'disableShadow', + value: function disableShadow(ctx) { + if (this.options.shadow.enabled === true) { + ctx.shadowColor = 'rgba(0,0,0,0)'; + ctx.shadowBlur = 0; + ctx.shadowOffsetX = 0; + ctx.shadowOffsetY = 0; + } + } + }]); + + return NodeBase; + })(); + + exports['default'] = NodeBase; + module.exports = exports['default']; + +/***/ }, +/* 105 */ +/***/ 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; }; })(); + + 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 _NodeBase2 = __webpack_require__(104); + + 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); + } + + _inherits(CircleImageBase, _NodeBase); + + _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; + } + 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: '_findBorderPosition', - value: function _findBorderPosition(nearNode, ctx) { - var options = arguments[2] === undefined ? {} : arguments[2]; + 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; - return this._findBorderPositionBezier(nearNode, ctx, options.via); + 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.fillStyle = selected ? this.options.color.highlight.background : hover ? this.options.color.hover.background : this.options.color.background; + ctx.circle(x, y, size); + + // draw shadow if enabled + this.enableShadow(ctx); + ctx.fill(); + + // disable shadows for other elements. + this.disableShadow(ctx); + + ctx.stroke(); } }, { - 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: '_drawImageAtPosition', + value: function _drawImageAtPosition(ctx) { + if (this.imageObj.width != 0) { + // draw the image + ctx.globalAlpha = 1; + + // draw shadow if enabled + this.enableShadow(ctx); + ctx.drawImage(this.imageObj, this.left, this.top, this.width, this.height); + + // disable shadows for other elements. + this.disableShadow(ctx); + } } }, { - 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 via = arguments[1] === undefined ? this._getViaCoordinates() : arguments[1]; + key: '_drawImageLabel', + value: function _drawImageLabel(ctx, x, y, selected) { + var yLabel; + var offset = 0; - 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; + if (this.height !== undefined) { + offset = this.height * 0.5; + var labelDimensions = this.labelModule.getTextSize(ctx); + if (labelDimensions.lineCount >= 1) { + offset += labelDimensions.height / 2; + } + } - return { x: x, y: y }; + yLabel = y + offset; + this.labelModule.draw(ctx, x, yLabel, selected, 'hanging'); } }]); - return BezierEdgeStatic; - })(_BezierEdgeBase3['default']); + return CircleImageBase; + })(_NodeBase3['default']); - exports['default'] = BezierEdgeStatic; + exports['default'] = CircleImageBase; module.exports = exports['default']; /***/ }, -/* 104 */ +/* 106 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -38362,102 +38077,231 @@ return /******/ (function(modules) { // webpackBootstrap value: true }); - var _EdgeBase2 = __webpack_require__(109); + var _NodeBase2 = __webpack_require__(104); - var _EdgeBase3 = _interopRequireWildcard(_EdgeBase2); + var _NodeBase3 = _interopRequireWildcard(_NodeBase2); - var StraightEdge = (function (_EdgeBase) { - function StraightEdge(options, body, labelModule) { - _classCallCheck(this, StraightEdge); + var ShapeBase = (function (_NodeBase) { + function ShapeBase(options, body, labelModule) { + _classCallCheck(this, ShapeBase); - _get(Object.getPrototypeOf(StraightEdge.prototype), 'constructor', this).call(this, options, body, labelModule); + _get(Object.getPrototypeOf(ShapeBase.prototype), 'constructor', this).call(this, options, body, labelModule); } - _inherits(StraightEdge, _EdgeBase); + _inherits(ShapeBase, _NodeBase); - _createClass(StraightEdge, [{ - key: 'cleanup', - value: function cleanup() { - return false; + _createClass(ShapeBase, [{ + key: '_resizeShape', + value: function _resizeShape() { + if (this.width === undefined) { + var size = 2 * this.options.size; + this.width = size; + this.height = size; + } } }, { - key: '_line', + key: '_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); + + // draw shadow if enabled + this.enableShadow(ctx); + ctx.fill(); + + // disable shadows for other elements. + this.disableShadow(ctx); + + 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; + + 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 ShapeBase; + })(_NodeBase3['default']); + + exports['default'] = ShapeBase; + module.exports = exports['default']; + +/***/ }, +/* 107 */ +/***/ 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; }; })(); + + 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 _EdgeBase2 = __webpack_require__(108); + + var _EdgeBase3 = _interopRequireWildcard(_EdgeBase2); + + 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(BezierEdgeBase, _EdgeBase); + + _createClass(BezierEdgeBase, [{ + key: '_findBorderPositionBezier', + + /** + * 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; + } + + 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; + } + } - /** - * 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); - // draw shadow if enabled - this.enableShadow(ctx); - ctx.stroke(); - this.disableShadow(ctx); - return undefined; + iteration++; + } + pos.t = middle; + + return pos; } }, { - key: 'getPoint', + key: '_getDistanceToBezierEdge', /** - * 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}} + * 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 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; + 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; } - 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; - - var borderPos = {}; - borderPos.x = (1 - toBorderPoint) * node2.x + toBorderPoint * node1.x; - borderPos.y = (1 - toBorderPoint) * node2.y + toBorderPoint * node1.y; - - 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 minDistance; } }]); - return StraightEdge; + return BezierEdgeBase; })(_EdgeBase3['default']); - exports['default'] = StraightEdge; + exports['default'] = BezierEdgeBase; module.exports = exports['default']; /***/ }, -/* 105 */ +/* 108 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; + 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 _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; }; })(); @@ -38465,415 +38309,577 @@ return /******/ (function(modules) { // webpackBootstrap Object.defineProperty(exports, '__esModule', { value: true }); + var util = __webpack_require__(1); - var NodeBase = (function () { - function NodeBase(options, body, labelModule) { - _classCallCheck(this, NodeBase); + var EdgeBase = (function () { + function EdgeBase(options, body, labelModule) { + _classCallCheck(this, EdgeBase); this.body = body; this.labelModule = labelModule; this.setOptions(options); - this.top = undefined; - this.left = undefined; - this.height = undefined; - this.boundingBox = { top: 0, left: 0, right: 0, bottom: 0 }; + this.colorDirty = true; + this.color = {}; + this.selectionWidth = 2; + this.hoverWidth = 1.5; } - _createClass(NodeBase, [{ + _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: '_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; - } + key: 'togglePhysics', + + /** + * overloadable if the shape has to toggle the via node to disabled + * @param status + */ + value: function togglePhysics(status) {} }, { - key: 'enableShadow', - value: function enableShadow(ctx) { - if (this.options.shadow.enabled === true) { - ctx.shadowColor = 'rgba(0,0,0,0.5)'; - ctx.shadowBlur = this.options.shadow.size; - ctx.shadowOffsetX = this.options.shadow.x; - ctx.shadowOffsetY = this.options.shadow.y; + key: 'drawLine', + + /** + * 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.options.dashes.enabled === true) { + via = this._drawDashedLine(ctx); + } else { + via = this._drawLine(ctx); } + return via; } }, { - key: 'disableShadow', - value: function disableShadow(ctx) { - if (this.options.shadow.enabled === true) { - ctx.shadowColor = 'rgba(0,0,0,0)'; - ctx.shadowBlur = 0; - ctx.shadowOffsetX = 0; - ctx.shadowOffsetY = 0; - } - } - }]); - - return NodeBase; - })(); - - exports['default'] = NodeBase; - module.exports = exports['default']; - -/***/ }, -/* 106 */ -/***/ 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; }; })(); - - 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 - }); + key: '_drawLine', + value: function _drawLine(ctx) { + var via = undefined; + if (this.from != this.to) { + // draw line + via = this._line(ctx); + } else { + var _getCircleData = this._getCircleData(ctx); - var _NodeBase2 = __webpack_require__(105); + var _getCircleData2 = _slicedToArray(_getCircleData, 3); - var _NodeBase3 = _interopRequireWildcard(_NodeBase2); + var x = _getCircleData2[0]; + var y = _getCircleData2[1]; + var radius = _getCircleData2[2]; - var CircleImageBase = (function (_NodeBase) { - function CircleImageBase(options, body, labelModule) { - _classCallCheck(this, CircleImageBase); + this._circle(ctx, x, y, radius); + } + return via; + } + }, { + key: '_drawDashedLine', + value: function _drawDashedLine(ctx) { + var via = undefined; + ctx.lineCap = 'round'; + var pattern = [5, 5]; + if (this.options.dashes.pattern !== undefined) { + if (Array.isArray(this.options.dashes.pattern) === true) { + pattern = this.options.dashes.pattern; + } + } - _get(Object.getPrototypeOf(CircleImageBase.prototype), 'constructor', this).call(this, options, body, labelModule); - } + // only firefox and chrome support this method, else we use the legacy one. + if (ctx.setLineDash !== undefined && this.options.dashes.altLength === undefined) { + ctx.save(); - _inherits(CircleImageBase, _NodeBase); + // set dash settings for chrome or firefox + ctx.setLineDash(pattern); + ctx.lineDashOffset = 0; - _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; - } - 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; + // draw the line + if (this.from != this.to) { + // draw line + via = this._line(ctx); } 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; + var _getCircleData3 = this._getCircleData(ctx); - ctx.strokeStyle = selected ? this.options.color.highlight.border : hover ? this.options.color.hover.border : this.options.color.border; + var _getCircleData32 = _slicedToArray(_getCircleData3, 3); - ctx.lineWidth = selected ? selectionLineWidth : borderWidth; - ctx.lineWidth *= this.networkScaleInv; - ctx.lineWidth = Math.min(this.width, ctx.lineWidth); + var x = _getCircleData32[0]; + var y = _getCircleData32[1]; + var radius = _getCircleData32[2]; - ctx.fillStyle = selected ? this.options.color.highlight.background : hover ? this.options.color.hover.background : this.options.color.background; - ctx.circle(x, y, size); + this._circle(ctx, x, y, radius); + } - // draw shadow if enabled - this.enableShadow(ctx); - ctx.fill(); + // restore the dash settings. + ctx.setLineDash([0]); + ctx.lineDashOffset = 0; + ctx.restore(); + } else { + // unsupporting smooth lines - // disable shadows for other elements. - this.disableShadow(ctx); + if (this.from != this.to) { + // draw line + ctx.dashedLine(this.from.x, this.from.y, this.to.x, this.to.y, pattern); + } else { + var _getCircleData4 = this._getCircleData(ctx); - ctx.stroke(); - } - }, { - key: '_drawImageAtPosition', - value: function _drawImageAtPosition(ctx) { - if (this.imageObj.width != 0) { - // draw the image - ctx.globalAlpha = 1; + var _getCircleData42 = _slicedToArray(_getCircleData4, 3); + + var x = _getCircleData42[0]; + var y = _getCircleData42[1]; + var radius = _getCircleData42[2]; + this._circle(ctx, x, y, radius); + } // draw shadow if enabled this.enableShadow(ctx); - ctx.drawImage(this.imageObj, this.left, this.top, this.width, this.height); + + ctx.stroke(); // disable shadows for other elements. this.disableShadow(ctx); } + return via; } }, { - 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; - } + 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); } - - yLabel = y + offset; - this.labelModule.draw(ctx, x, yLabel, selected, 'hanging'); } - }]); + }, { + 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 _getCircleData5 = this._getCircleData(ctx); - return CircleImageBase; - })(_NodeBase3['default']); + var _getCircleData52 = _slicedToArray(_getCircleData5, 3); - exports['default'] = CircleImageBase; - module.exports = exports['default']; + var x = _getCircleData52[0]; + var y = _getCircleData52[1]; + var radius = _getCircleData52[2]; -/***/ }, -/* 107 */ -/***/ 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); + } + } - var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; + // 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', - var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; + /** + * 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 _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 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 _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 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; - 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; }; + while (low <= high && iteration < maxIterations) { + middle = (low + high) * 0.5; - Object.defineProperty(exports, '__esModule', { - value: true - }); + 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 _NodeBase2 = __webpack_require__(105); + return pos; + } + }, { + key: 'getLineWidth', - var _NodeBase3 = _interopRequireWildcard(_NodeBase2); + /** + * 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(this.selectionWidth, 0.3 / this.body.view.scale); + } else { + if (hover === true) { + return Math.max(this.hoverWidth, 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 !== false) { + // when this is a loop edge, just use the 'from' method + if (colorOptions.inherit === 'both' && this.from.id !== this.to.id) { + 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 ShapeBase = (function (_NodeBase) { - function ShapeBase(options, body, labelModule) { - _classCallCheck(this, ShapeBase); + // -------------------- this returns -------------------- // + return grd; + } - _get(Object.getPrototypeOf(ShapeBase.prototype), 'constructor', this).call(this, options, body, labelModule); - } + if (this.colorDirty === true) { + if (colorOptions.inherit === '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); + } - _inherits(ShapeBase, _NodeBase); + // if color inherit is on and gradients are used, the function has already returned by now. + this.colorDirty = false; - _createClass(ShapeBase, [{ - key: '_resizeShape', - value: function _resizeShape() { - if (this.width === undefined) { - var size = 2 * this.options.size; - this.width = size; - this.height = size; + if (this.selected === true) { + return this.color.highlight; + } else if (this.hover === true) { + return this.color.hover; + } else { + return this.color.color; } } }, { - key: '_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); + key: '_circle', + /** + * 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 shadow if enabled this.enableShadow(ctx); - ctx.fill(); - - // disable shadows for other elements. - this.disableShadow(ctx); + // draw a circle + ctx.beginPath(); + ctx.arc(x, y, radius, 0, 2 * Math.PI, false); 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; - - 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); - } + // disable shadows for other elements. + this.disableShadow(ctx); } - }]); - - return ShapeBase; - })(_NodeBase3['default']); - - exports['default'] = ShapeBase; - module.exports = exports['default']; - -/***/ }, -/* 108 */ -/***/ 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; }; })(); + }, { + key: 'getDistanceToEdge', - 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); } }; + /** + * 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 _getCircleData6 = this._getCircleData(); - 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 _getCircleData62 = _slicedToArray(_getCircleData6, 3); - Object.defineProperty(exports, '__esModule', { - value: true - }); + var x = _getCircleData62[0]; + var y = _getCircleData62[1]; + var radius = _getCircleData62[2]; - var _EdgeBase2 = __webpack_require__(109); + var dx = x - x3; + var dy = y - y3; + returnValue = Math.abs(Math.sqrt(dx * dx + dy * dy) - radius); + } - var _EdgeBase3 = _interopRequireWildcard(_EdgeBase2); + 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; - var BezierEdgeBase = (function (_EdgeBase) { - function BezierEdgeBase(options, body, labelModule) { - _classCallCheck(this, BezierEdgeBase); + if (u > 1) { + u = 1; + } else if (u < 0) { + u = 0; + } - _get(Object.getPrototypeOf(BezierEdgeBase.prototype), 'constructor', this).call(this, options, body, labelModule); - } + var x = x1 + u * px; + var y = y1 + u * py; + var dx = x - x3; + var dy = y - y3; - _inherits(BezierEdgeBase, _EdgeBase); + //# 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 - _createClass(BezierEdgeBase, [{ - key: '_findBorderPositionBezier', + return Math.sqrt(dx * dx + dy * dy); + } + }, { + key: 'drawArrowHead', /** - * 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 position * @param viaNode */ - value: function _findBorderPositionBezier(nearNode, ctx) { - var viaNode = arguments[2] === undefined ? this._getViaCoordinates() : arguments[2]; + 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); - 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; + // 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; } - while (low <= high && iteration < maxIterations) { - var middle = (low + high) * 0.5; + // 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); + + // draw shadow if enabled + this.enableShadow(ctx); + ctx.fill(); + + // disable shadows for other elements. + this.disableShadow(ctx); + ctx.stroke(); + } else { + // draw circle + var _angle = undefined, + point = undefined; + + var _getCircleData7 = this._getCircleData(ctx); - 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; - } + var _getCircleData72 = _slicedToArray(_getCircleData7, 3); + + var x = _getCircleData72[0]; + var y = _getCircleData72[1]; + var radius = _getCircleData72[2]; + + 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 { - if (from === false) { - high = middle; - } else { - low = middle; - } + point = this._pointOnCircle(x, y, radius, 0.175); + _angle = 3.9269908169872414; // === 0.175 * -2 * Math.PI + 1.5 * Math.PI + 0.1 * Math.PI; } - iteration++; - } - pos.t = middle; + // draw the arrowhead + var _length = (10 + 5 * this.options.width) * scaleFactor; + ctx.arrow(point.x, point.y, _angle, _length); - return pos; + // draw shadow if enabled + this.enableShadow(ctx); + ctx.fill(); + + // disable shadows for other elements. + this.disableShadow(ctx); + ctx.stroke(); + } } }, { - key: '_getDistanceToBezierEdge', - - /** - * 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; + key: 'enableShadow', + value: function enableShadow(ctx) { + if (this.options.shadow.enabled === true) { + ctx.shadowColor = 'rgba(0,0,0,0.5)'; + ctx.shadowBlur = this.options.shadow.size; + ctx.shadowOffsetX = this.options.shadow.x; + ctx.shadowOffsetY = this.options.shadow.y; + } + } + }, { + key: 'disableShadow', + value: function disableShadow(ctx) { + if (this.options.shadow.enabled === true) { + ctx.shadowColor = 'rgba(0,0,0,0)'; + ctx.shadowBlur = 0; + ctx.shadowOffsetX = 0; + ctx.shadowOffsetY = 0; } - - return minDistance; } }]); - return BezierEdgeBase; - })(_EdgeBase3['default']); + return EdgeBase; + })(); - exports['default'] = BezierEdgeBase; + exports['default'] = EdgeBase; module.exports = exports['default']; /***/ }, @@ -38882,8 +38888,6 @@ return /******/ (function(modules) { // webpackBootstrap 'use strict'; - 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 _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; }; })(); @@ -38891,577 +38895,570 @@ return /******/ (function(modules) { // webpackBootstrap Object.defineProperty(exports, '__esModule', { value: true }); + var Hammer = __webpack_require__(41); + var hammerUtil = __webpack_require__(45); var util = __webpack_require__(1); - var EdgeBase = (function () { - function EdgeBase(options, body, labelModule) { - _classCallCheck(this, EdgeBase); + var ColorPicker = (function () { + function ColorPicker() { + var pixelRatio = arguments[0] === undefined ? 1 : arguments[0]; - this.body = body; - this.labelModule = labelModule; - this.setOptions(options); - this.colorDirty = true; - this.color = {}; - this.selectionWidth = 2; - this.hoverWidth = 1.5; + _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(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: 'togglePhysics', + _createClass(ColorPicker, [{ + key: 'insertTo', /** - * overloadable if the shape has to toggle the via node to disabled - * @param status + * this inserts the colorPicker into a div from the DOM + * @param container */ - value: function togglePhysics(status) {} + 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: 'drawLine', + key: 'setCallback', /** - * 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 + * the callback is executed on apply and save. Bind it to the application + * @param callback */ - value: function drawLine(ctx, selected, hover) { - // set style - ctx.strokeStyle = this.getColor(ctx); - ctx.lineWidth = this.getLineWidth(selected, hover); - var via = undefined; - if (this.options.dashes.enabled === true) { - via = this._drawDashedLine(ctx); + value: function setCallback(callback) { + if (typeof callback === 'function') { + this.updateCallback = callback; } else { - via = this._drawLine(ctx); + throw new Error('Function attempted to set as colorPicker callback is not a function.'); } - return via; } }, { - key: '_drawLine', - value: function _drawLine(ctx) { - var via = undefined; - if (this.from != this.to) { - // draw line - via = this._line(ctx); - } else { - var _getCircleData = this._getCircleData(ctx); - - var _getCircleData2 = _slicedToArray(_getCircleData, 3); - - var x = _getCircleData2[0]; - var y = _getCircleData2[1]; - var radius = _getCircleData2[2]; - - this._circle(ctx, x, y, radius); + 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]; } - return via; } }, { - key: '_drawDashedLine', - value: function _drawDashedLine(ctx) { - var via = undefined; - ctx.lineCap = 'round'; - var pattern = [5, 5]; - if (this.options.dashes.pattern !== undefined) { - if (Array.isArray(this.options.dashes.pattern) === true) { - pattern = this.options.dashes.pattern; - } - } - - // only firefox and chrome support this method, else we use the legacy one. - if (ctx.setLineDash !== undefined && this.options.dashes.altLength === undefined) { - ctx.save(); + key: 'setColor', - // set dash settings for chrome or firefox - ctx.setLineDash(pattern); - ctx.lineDashOffset = 0; + /** + * 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]; - // draw the line - if (this.from != this.to) { - // draw line - via = this._line(ctx); - } else { - var _getCircleData3 = this._getCircleData(ctx); + if (color === 'none') { + return; + } - var _getCircleData32 = _slicedToArray(_getCircleData3, 3); + var rgba = undefined; - var x = _getCircleData32[0]; - var y = _getCircleData32[1]; - var radius = _getCircleData32[2]; + // if a html color shorthand is used, convert to hex + var htmlColor = this._isColorString(color); + if (htmlColor !== undefined) { + color = htmlColor; + } - this._circle(ctx, x, y, radius); + // 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 }; } - - // restore the dash settings. - ctx.setLineDash([0]); - ctx.lineDashOffset = 0; - ctx.restore(); } else { - // unsupporting smooth lines - - if (this.from != this.to) { - // draw line - ctx.dashedLine(this.from.x, this.from.y, this.to.x, this.to.y, pattern); - } else { - var _getCircleData4 = this._getCircleData(ctx); - - var _getCircleData42 = _slicedToArray(_getCircleData4, 3); - - var x = _getCircleData42[0]; - var y = _getCircleData42[1]; - var radius = _getCircleData42[2]; - - this._circle(ctx, x, y, radius); + 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 }; + } } - // draw shadow if enabled - this.enableShadow(ctx); - - ctx.stroke(); + } - // disable shadows for other elements. - this.disableShadow(ctx); + // 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); } - 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: '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: '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 _getCircleData5 = this._getCircleData(ctx); + key: '_hide', - var _getCircleData52 = _slicedToArray(_getCircleData5, 3); + // ------------------------------------------ PRIVATE ----------------------------- // - var x = _getCircleData52[0]; - var y = _getCircleData52[1]; - var radius = _getCircleData52[2]; + /** + * 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]; - 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 }); + // store the previous color for next time; + if (storePrevious === true) { + this.previousColor = util.extend({}, this.color); } - 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; - if (ctx !== undefined) { - if (node.shape.width === undefined) { - node.shape.resize(ctx); - } + if (this.applied === true) { + this.updateCallback(this.initialColor); } - // 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]; + this.frame.style.display = 'none'; } }, { - key: '_pointOnCircle', + key: '_save', /** - * 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 + * bound to the save button. Saves and hides. * @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) - }; + value: function _save() { + this.updateCallback(this.color); + this.applied = false; + this._hide(); } }, { - key: '_findBorderPositionCircle', + key: '_apply', /** - * 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 {*} + * Bound to apply button. Saves but does not close. Is undone by the cancel button. * @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; + value: function _apply() { + this.applied = true; + this.updateCallback(this.color); + this._updatePicker(this.color); + } + }, { + key: '_loadLast', - 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; + /** + * 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', - while (low <= high && iteration < maxIterations) { - middle = (low + high) * 0.5; + /** + * set the color, place the picker + * @param rgba + * @param setInitial + * @private + */ + value: function _setColor(rgba) { + var setInitial = arguments[1] === undefined ? true : arguments[1]; - 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++; + // store the initial color + if (setInitial === true) { + this.initialColor = util.extend({}, rgba); } - pos.t = middle; - return pos; + 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: 'getLineWidth', + key: '_setBrightness', /** - * Get the line width of the edge. Depends on width and whether one of the - * connected nodes is selected. - * @return {Number} width + * bound to brightness control + * @param value * @private */ - value: function getLineWidth(selected, hover) { - if (selected === true) { - return Math.max(this.selectionWidth, 0.3 / this.body.view.scale); - } else { - if (hover === true) { - return Math.max(this.hoverWidth, 0.3 / this.body.view.scale); - } else { - return Math.max(this.options.width, 0.3 / this.body.view.scale); - } - } + 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: 'getColor', - value: function getColor(ctx) { - var colorOptions = this.options.color; + key: '_updatePicker', - if (colorOptions.inherit !== false) { - // when this is a loop edge, just use the 'from' method - if (colorOptions.inherit === 'both' && this.from.id !== this.to.id) { - 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; + /** + * 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]; - 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 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); - // -------------------- this returns -------------------- // - return grd; - } + // clear the canvas + var w = this.colorPickerCanvas.clientWidth; + var h = this.colorPickerCanvas.clientHeight; + ctx.clearRect(0, 0, w, h); - if (this.colorDirty === true) { - if (colorOptions.inherit === '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); - } + 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(); - // if color inherit is on and gradients are used, the function has already returned by now. - this.colorDirty = false; + this.brightnessRange.value = 100 * hsv.v; + this.opacityRange.value = 100 * rgba.a; - if (this.selected === true) { - return this.color.highlight; - } else if (this.hover === true) { - return this.color.hover; - } else { - return this.color.color; - } + 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: '_circle', + key: '_setSize', /** - * Draw a line from a node to itself, a circle - * @param {CanvasRenderingContext2D} ctx - * @param {Number} x - * @param {Number} y - * @param {Number} radius + * used by create to set the size of the canvas. * @private */ - value: function _circle(ctx, x, y, radius) { - // draw shadow if enabled - this.enableShadow(ctx); - - // draw a circle - ctx.beginPath(); - ctx.arc(x, y, radius, 0, 2 * Math.PI, false); - ctx.stroke(); + value: function _setSize() { + this.colorPickerCanvas.style.width = '100%'; + this.colorPickerCanvas.style.height = '100%'; - // disable shadows for other elements. - this.disableShadow(ctx); + this.colorPickerCanvas.width = 289 * this.pixelRatio; + this.colorPickerCanvas.height = 289 * this.pixelRatio; } }, { - key: 'getDistanceToEdge', + key: '_create', /** - * 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 + * create all dom elements + * TODO: cleanup, lots of similar dom elements * @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); + value: function _create() { + this.frame = document.createElement('div'); + this.frame.className = 'vis-color-picker'; + + this.colorPickerDiv = document.createElement('div'); + this.colorPickerSelector = document.createElement('div'); + this.colorPickerSelector.className = 'vis-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 _getCircleData6 = this._getCircleData(); + var ctx = this.colorPickerCanvas.getContext('2d'); + this.pixelRatio = (window.devicePixelRatio || 1) / (ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1); - var _getCircleData62 = _slicedToArray(_getCircleData6, 3); + this.colorPickerCanvas.getContext('2d').setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0); + } - var x = _getCircleData62[0]; - var y = _getCircleData62[1]; - var radius = _getCircleData62[2]; + this.colorPickerDiv.className = 'vis-color'; + + this.opacityDiv = document.createElement('div'); + this.opacityDiv.className = 'vis-opacity'; + + this.brightnessDiv = document.createElement('div'); + this.brightnessDiv.className = 'vis-brightness'; + + this.arrowDiv = document.createElement('div'); + this.arrowDiv.className = 'vis-arrow'; + + this.opacityRange = document.createElement('input'); + this.opacityRange.type = 'range'; + this.opacityRange.min = '0'; + this.opacityRange.max = '100'; + this.opacityRange.value = '100'; + this.opacityRange.className = 'vis-range'; + + this.brightnessRange = document.createElement('input'); + this.brightnessRange.type = 'range'; + this.brightnessRange.min = '0'; + this.brightnessRange.max = '100'; + this.brightnessRange.value = '100'; + this.brightnessRange.className = 'vis-range'; + + 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 = 'vis-label vis-brightness'; + this.brightnessLabel.innerHTML = 'brightness:'; + + this.opacityLabel = document.createElement('div'); + this.opacityLabel.className = 'vis-label vis-opacity'; + this.opacityLabel.innerHTML = 'opacity:'; + + this.newColorDiv = document.createElement('div'); + this.newColorDiv.className = 'vis-new-color'; + this.newColorDiv.innerHTML = 'new'; + + this.initialColorDiv = document.createElement('div'); + this.initialColorDiv.className = 'vis-initial-color'; + this.initialColorDiv.innerHTML = 'initial'; + + this.cancelButton = document.createElement('div'); + this.cancelButton.className = 'vis-button vis-cancel'; + this.cancelButton.innerHTML = 'cancel'; + this.cancelButton.onclick = this._hide.bind(this, false); + + this.applyButton = document.createElement('div'); + this.applyButton.className = 'vis-button vis-apply'; + this.applyButton.innerHTML = 'apply'; + this.applyButton.onclick = this._apply.bind(this); + + this.saveButton = document.createElement('div'); + this.saveButton.className = 'vis-button vis-save'; + this.saveButton.innerHTML = 'save'; + this.saveButton.onclick = this._save.bind(this); + + this.loadButton = document.createElement('div'); + this.loadButton.className = 'vis-button vis-load'; + this.loadButton.innerHTML = 'load last'; + this.loadButton.onclick = this._loadLast.bind(this); - var dx = x - x3; - var dy = y - y3; - returnValue = Math.abs(Math.sqrt(dx * dx + dy * dy) - radius); - } + 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); - 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; - } + this.frame.appendChild(this.cancelButton); + this.frame.appendChild(this.applyButton); + this.frame.appendChild(this.saveButton); + this.frame.appendChild(this.loadButton); } }, { - 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; - } + key: '_bindHammer', - var x = x1 + u * px; - var y = y1 + u * py; - var dx = x - x3; - var dy = y - y3; + /** + * bind hammer to the color picker + * @private + */ + value: function _bindHammer() { + var _this = this; - //# 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 + this.drag = {}; + this.pinch = {}; + this.hammer = new Hammer(this.colorPickerCanvas); + this.hammer.get('pinch').set({ enable: true }); - return Math.sqrt(dx * dx + dy * dy); + 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: 'drawArrowHead', + key: '_generateHueCircle', /** - * - * @param ctx - * @param position - * @param viaNode + * generate the hue circle. This is relatively heavy (200ms) and is done only once on the first time it is shown. + * @private */ - 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; + 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); - 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; - } + // clear the canvas + var w = this.colorPickerCanvas.clientWidth; + var h = this.colorPickerCanvas.clientHeight; + ctx.clearRect(0, 0, w, h); - // 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); + // 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); } - } 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.strokeStyle = 'rgba(0,0,0,1)'; + ctx.circle(this.centerCoordinates.x, this.centerCoordinates.y, this.r); + ctx.stroke(); - // draw shadow if enabled - this.enableShadow(ctx); - ctx.fill(); + this.hueCircle = ctx.getImageData(0, 0, w, h); + } + this.generated = true; + } + }, { + key: '_moveSelector', - // disable shadows for other elements. - this.disableShadow(ctx); - ctx.stroke(); - } else { - // draw circle - var _angle = undefined, - point = undefined; + /** + * 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 _getCircleData7 = this._getCircleData(ctx); + var centerY = 0.5 * this.colorPickerDiv.clientHeight; + var centerX = 0.5 * this.colorPickerDiv.clientWidth; - var _getCircleData72 = _slicedToArray(_getCircleData7, 3); + var x = left - centerX; + var y = top - centerY; - var x = _getCircleData72[0]; - var y = _getCircleData72[1]; - var radius = _getCircleData72[2]; + var angle = Math.atan2(x, y); + var radius = 0.98 * Math.min(Math.sqrt(x * x + y * y), centerX); - 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; - } + var newTop = Math.cos(angle) * radius + centerY; + var newLeft = Math.sin(angle) * radius + centerX; - // draw the arrowhead - var _length = (10 + 5 * this.options.width) * scaleFactor; - ctx.arrow(point.x, point.y, _angle, _length); + this.colorPickerSelector.style.top = newTop - 0.5 * this.colorPickerSelector.clientHeight + 'px'; + this.colorPickerSelector.style.left = newLeft - 0.5 * this.colorPickerSelector.clientWidth + 'px'; - // draw shadow if enabled - this.enableShadow(ctx); - ctx.fill(); + // 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; - // disable shadows for other elements. - this.disableShadow(ctx); - ctx.stroke(); - } - } - }, { - key: 'enableShadow', - value: function enableShadow(ctx) { - if (this.options.shadow.enabled === true) { - ctx.shadowColor = 'rgba(0,0,0,0.5)'; - ctx.shadowBlur = this.options.shadow.size; - ctx.shadowOffsetX = this.options.shadow.x; - ctx.shadowOffsetY = this.options.shadow.y; - } - } - }, { - key: 'disableShadow', - value: function disableShadow(ctx) { - if (this.options.shadow.enabled === true) { - ctx.shadowColor = 'rgba(0,0,0,0)'; - ctx.shadowBlur = 0; - ctx.shadowOffsetX = 0; - ctx.shadowOffsetY = 0; - } + // 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 + ')'; } }]); - return EdgeBase; + return ColorPicker; })(); - exports['default'] = EdgeBase; + exports['default'] = ColorPicker; module.exports = exports['default']; /***/ } diff --git a/docs/network/configure.html b/docs/network/configure.html index c7ff4892..035f9465 100644 --- a/docs/network/configure.html +++ b/docs/network/configure.html @@ -118,6 +118,13 @@ network.setOptions(options); default description + + enabled + Boolean + true + + + filter String or Array or Boolean diff --git a/lib/network/Network.js b/lib/network/Network.js index f3871b87..24922640 100644 --- a/lib/network/Network.js +++ b/lib/network/Network.js @@ -26,7 +26,7 @@ import ManipulationSystem from "./modules/ManipulationSystem"; import ConfigurationSystem from "./modules/ConfigurationSystem"; import Validator from "./modules/Validator"; import {printStyle} from "./modules/Validator"; -import allOptions from './modules/components/AllOptions.js'; +import {allOptions, configureOptions} from './modules/components/AllOptions.js'; /** * @constructor Network @@ -112,11 +112,12 @@ function Network(container, data, options) { this.nodesHandler = new NodesHandler(this.body, this.images, this.groups, this.layoutEngine); // Handle adding, deleting and updating of nodes as well as global options this.edgesHandler = new EdgesHandler(this.body, this.images, this.groups); // Handle adding, deleting and updating of edges as well as global options - this.configurationSystem = new ConfigurationSystem(this); - // create the DOM elements this.canvas._create(); + // setup configuration system + this.configurationSystem = new ConfigurationSystem(this, this.body.container, configureOptions, this.canvas.pixelRatio); + // apply options this.setOptions(options); @@ -158,7 +159,21 @@ Network.prototype.setOptions = function (options) { this.clustering.setOptions(options.clustering); this.manipulation.setOptions(options.manipulation); - this.configurationSystem.setOptions(options); + this.configurationSystem.setOptions(options.configure); + + // if the configuration system is enabled, copy all options and put them into the config system + if (this.configurationSystem.options.enabled === true) { + let networkOptions = {nodes:{},edges:{},layout:{},interaction:{},manipulation:{},physics:{},selection:{},rendering:{}}; + util.deepExtend(networkOptions.nodes, this.nodesHandler.options); + util.deepExtend(networkOptions.edges, this.edgesHandler.options); + util.deepExtend(networkOptions.layout, this.layoutEngine.options); + util.deepExtend(networkOptions.interaction, this.interactionHandler.options); + util.deepExtend(networkOptions.manipulation, this.manipulation.options); + util.deepExtend(networkOptions.physics, this.physics.options); + util.deepExtend(networkOptions.selection, this.selectionHandler.options); + util.deepExtend(networkOptions.rendering, this.renderer.options); + this.configurationSystem.setModuleOptions(networkOptions); + } // handle network global options if (options.clickToUse !== undefined) { diff --git a/lib/network/modules/ConfigurationSystem.js b/lib/network/modules/ConfigurationSystem.js index 711d46c5..93df2a4e 100644 --- a/lib/network/modules/ConfigurationSystem.js +++ b/lib/network/modules/ConfigurationSystem.js @@ -1,6 +1,6 @@ var util = require('../../util'); -import ColorPicker from './components/ColorPicker' +import ColorPicker from './components/ColorPicker' /** * The way this works is for all properties of this.possible options, you can supply the property name in any form to list the options. @@ -11,203 +11,29 @@ import ColorPicker from './components/ColorPicker' * * The options are matched with their counterparts in each of the modules and the values used in the configuration are * + * @param parentModule | the location where parentModule.setOptions() can be called + * @param defaultContainer | the default container of the module + * @param configureOptions | the fully configured and predefined options set found in allOptions.js + * @param pixelRatio | canvas pixel ratio */ class ConfigurationSystem { - constructor(network) { - this.network = network; + constructor(parentModule, defaultContainer, configureOptions, pixelRatio = 1) { + this.parent = parentModule; this.changedOptions = []; + this.container = defaultContainer; - this.possibleOptions = { - nodes: { - borderWidth: [1, 0, 10, 1], - borderWidthSelected: [2, 0, 10, 1], - color: { - border: ['color','#2B7CE9'], - background: ['color','#97C2FC'], - highlight: { - border: ['color','#2B7CE9'], - background: ['color','#D2E5FF'] - }, - hover: { - border: ['color','#2B7CE9'], - background: ['color','#D2E5FF'] - } - }, - fixed: { - x: false, - y: false - }, - font: { - color: ['color','#343434'], - size: [14, 0, 100, 1], // px - face: ['arial', 'verdana', 'tahoma'], - background: ['color','none'], - stroke: [0, 0, 50, 1], // px - strokeColor: ['color','#ffffff'] - }, - //group: 'string', - hidden: false, - //icon: { - // face: 'string', //'FontAwesome', - // code: 'string', //'\uf007', - // size: [50, 0, 200, 1], //50, - // color: ['color','#2B7CE9'] //'#aa00ff' - //}, - //image: 'string', // --> URL - physics: true, - scaling: { - min: [10, 0, 200, 1], - max: [30, 0, 200, 1], - label: { - enabled: true, - min: [14, 0, 200, 1], - max: [30, 0, 200, 1], - maxVisible: [30, 0, 200, 1], - drawThreshold: [3, 0, 20, 1] - } - }, - shadow:{ - enabled: false, - size:[10, 0, 20, 1], - x:[5, -30, 30, 1], - y:[5, -30, 30, 1] - }, - shape: ['ellipse', 'box', 'circle', 'database', 'diamond', 'dot', 'square', 'star', 'text', 'triangle', 'triangleDown'], - size: [25, 0, 200, 1] - }, - edges: { - arrows: { - to: {enabled: false, scaleFactor: [1, 0, 3, 0.05]}, // boolean / {arrowScaleFactor:1} / {enabled: false, arrowScaleFactor:1} - middle: {enabled: false, scaleFactor: [1, 0, 3, 0.05]}, - from: {enabled: false, scaleFactor: [1, 0, 3, 0.05]} - }, - color: { - color: ['color','#848484'], - highlight: ['color','#848484'], - hover: ['color','#848484'], - inherit: ['from','to','both',true, false], - opacity: [1, 0, 1, 0.05] - }, - dashes: false, - font: { - color: ['color','#343434'], - size: [14, 0, 100, 1], // px - face: ['arial', 'verdana', 'tahoma'], - background: ['color','none'], - stroke: [1, 0, 50, 1], // px - strokeColor: ['color','#ffffff'], - align: ['horizontal', 'top', 'middle', 'bottom'] - }, - hidden: false, - hoverWidth: [2, 0, 5, 0.1], - physics: true, - scaling: { - min: [1, 0, 100, 1], - max: [15, 0, 100, 1], - label: { - enabled: true, - min: [14, 0, 200, 1], - max: [30, 0, 200, 1], - maxVisible: [30, 0, 200, 1], - drawThreshold: [3, 0, 20, 1] - } - }, - selectionWidth: [1.5, 0, 5, 0.1], - selfReferenceSize: [20, 0, 200, 1], - shadow:{ - enabled: false, - size:[10, 0, 20, 1], - x:[5, -30, 30, 1], - y:[5, -30, 30, 1] - }, - smooth: { - enabled: true, - dynamic: true, - type: ['continuous', 'discrete', 'diagonalCross', 'straightCross', 'horizontal', 'vertical', 'curvedCW', 'curvedCCW'], - roundness: [0.5, 0, 1, 0.05] - }, - width: [1, 0, 30, 1] - }, - layout: { - randomSeed: [0, 0, 500, 1], - hierarchical: { - enabled: false, - levelSeparation: [150, 20, 500, 5], - direction: ['UD', 'DU', 'LR', 'RL'], // UD, DU, LR, RL - sortMethod: ['hubsize', 'directed'] // hubsize, directed - } - }, - interaction: { - dragNodes: true, - dragView: true, - zoomView: true, - hoverEnabled: false, - navigationButtons: false, - tooltipDelay: [300, 0, 1000, 25], - keyboard: { - enabled: false, - speed: {x: [10, 0, 40, 1], y: [10, 0, 40, 1], zoom: [0.02, 0, 0.1, 0.005]}, - bindToWindow: true - } - }, - manipulation: { - enabled: false, - initiallyActive: false, - locale: ['en', 'nl'] - }, - physics: { - barnesHut: { - //theta: [0.5, 0.1, 1, 0.05], - gravitationalConstant: [-2000, -30000, 0, 50], - centralGravity: [0.3, 0, 10, 0.05], - springLength: [95, 0, 500, 5], - springConstant: [0.04, 0, 5, 0.005], - damping: [0.09, 0, 1, 0.01] - }, - repulsion: { - centralGravity: [0.2, 0, 10, 0.05], - springLength: [200, 0, 500, 5], - springConstant: [0.05, 0, 5, 0.005], - nodeDistance: [100, 0, 500, 5], - damping: [0.09, 0, 1, 0.01] - }, - hierarchicalRepulsion: { - centralGravity: [0.2, 0, 10, 0.05], - springLength: [100, 0, 500, 5], - springConstant: [0.01, 0, 5, 0.005], - nodeDistance: [120, 0, 500, 5], - damping: [0.09, 0, 1, 0.01] - }, - maxVelocity: [50, 0, 150, 1], - minVelocity: [0.1, 0.01, 0.5, 0.01], - solver: ['barnesHut', 'repulsion', 'hierarchicalRepulsion'], - timestep: [0.5, 0, 1, 0.05] - }, - selection: { - selectable: true, - selectConnectedEdges: true - }, - rendering: { - hideEdgesOnDrag: false, - hideNodesOnDrag: false - } - }; - - this.actualOptions = { - nodes:{}, - edges:{}, - layout:{}, - interaction:{}, - manipulation:{}, - physics:{}, - selection:{}, - rendering:{}, - configure: false, - configureContainer: undefined - }; + this.options = {}; + this.defaultOptions = { + enabled: false, + filter: true, + container: undefined + } + util.extend(this.options, this.defaultOptions); + this.configureOptions = configureOptions; + this.moduleOptions = {}; this.domElements = []; - this.colorPicker = new ColorPicker(this.network.canvas.pixelRatio); + this.colorPicker = new ColorPicker(pixelRatio); this.wrapper; } @@ -220,45 +46,42 @@ class ConfigurationSystem { */ setOptions(options) { if (options !== undefined) { - util.extend(this.actualOptions, options); - } - - 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.rendering, this.network.renderer.selection, true); - - - this.container = this.network.body.container; - let config = true; - if (typeof this.actualOptions.configure === 'string') { - config = this.actualOptions.configure; + let enabled = true; + if (typeof options === 'string') { + this.options.filter = options; } - else if (this.actualOptions.configure instanceof Array) { - config = this.actualOptions.configure.join(); + else if (options instanceof Array) { + this.options.filter = options.join(); } - else if (typeof this.actualOptions.configure === 'object') { - if (this.actualOptions.configure.container !== undefined) { - this.container = this.actualOptions.configure.container; + else if (typeof options === 'object') { + if (options.container !== undefined) { + this.options.container = options.container; } - if (this.actualOptions.configure.filter !== undefined) { - config = this.actualOptions.configure.filter; + if (options.filter !== undefined) { + this.options.filter = options.filter; + } + if (options.enabled !== undefined) { + enabled = options.enabled; } } - else if (typeof this.actualOptions.configure === 'boolean') { - config = this.actualOptions.configure; + else if (typeof options === 'boolean') { + this.options.filter = true; + enabled = options; } + this.options.enabled = enabled; + } + this._clean(); + } + - if (config !== false) { - this._create(config); + setModuleOptions(moduleOptions) { + this.moduleOptions = moduleOptions; + if (this.options.enabled === true) { + this._clean(); + if (this.options.container !== undefined) { + this.container = this.options.container; } + this._create(this.options.filter); } } @@ -272,10 +95,10 @@ class ConfigurationSystem { this.changedOptions = []; let counter = 0; - for (let option in this.possibleOptions) { - if (this.possibleOptions.hasOwnProperty(option)) { + for (let option in this.configureOptions) { + if (this.configureOptions.hasOwnProperty(option)) { if (config === true || config.indexOf(option) !== -1) { - let optionObj = this.possibleOptions[option]; + let optionObj = this.configureOptions[option]; // linebreak between categories if (counter > 0) { @@ -322,6 +145,7 @@ class ConfigurationSystem { } } + /** * delete all DOM elements * @private @@ -338,6 +162,7 @@ class ConfigurationSystem { this.domElements = []; } + /** * get the value from the actualOptions if it exists * @param {array} path | where to look for the actual option @@ -345,7 +170,7 @@ class ConfigurationSystem { * @private */ _getValue(path) { - let base = this.actualOptions; + let base = this.moduleOptions; for (let i = 0; i < path.length; i++) { if (base[path[i]] !== undefined) { base = base[path[i]]; @@ -359,22 +184,6 @@ class ConfigurationSystem { } - /** - * 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 - */ - _addToPath(path, newValue) { - let newPath = []; - for (let i = 0; i < path.length; i++) { - newPath.push(path[i]); - } - newPath.push(newValue); - return newPath; - } - /** * all option elements are wrapped in an item * @param path @@ -390,6 +199,7 @@ class ConfigurationSystem { this.domElements.push(item); } + /** * header for major subjects * @param name @@ -402,6 +212,7 @@ class ConfigurationSystem { this._makeItem([],div); } + /** * make a label, if it is an object label, it gets different styling. * @param name @@ -616,7 +427,7 @@ class ConfigurationSystem { // collapse the physics options that are not enabled let draw = true; if (path.indexOf('physics') !== -1) { - if (this.actualOptions.physics.solver !== subObj) { + if (this.moduleOptions.physics.solver !== subObj) { draw = false; } } @@ -683,7 +494,7 @@ class ConfigurationSystem { */ _update(value, path) { let options = this._constructOptions(value,path); - this.network.setOptions(options); + this.parent.setOptions(options); } _constructOptions(value, path, optionsObj = {}) { @@ -704,7 +515,6 @@ class ConfigurationSystem { pointer[path[i]] = value; } } - console.log(optionsObj) return optionsObj; } diff --git a/lib/network/modules/components/AllOptions.js b/lib/network/modules/components/AllOptions.js index 4a1cf7e7..7e85b0b3 100644 --- a/lib/network/modules/components/AllOptions.js +++ b/lib/network/modules/components/AllOptions.js @@ -29,9 +29,10 @@ let allOptions = { }, clustering: {}, configure: { + enabled: {boolean}, filter: {boolean,string:['nodes','edges','layout','physics','manipulation','interaction','selection','rendering'],array}, container: {dom}, - __type__: {object,string,array,boolean} + __type__: {object,boolean,string:['nodes','edges','layout','physics','manipulation','interaction','selection','rendering'],array} }, edges: { arrows: { @@ -273,8 +274,187 @@ let allOptions = { __type__: {object} }; - allOptions.groups.__any__ = allOptions.nodes; allOptions.manipulation.controlNodeStyle = allOptions.nodes; -export default allOptions; \ No newline at end of file + +let configureOptions = { + nodes: { + borderWidth: [1, 0, 10, 1], + borderWidthSelected: [2, 0, 10, 1], + color: { + border: ['color','#2B7CE9'], + background: ['color','#97C2FC'], + highlight: { + border: ['color','#2B7CE9'], + background: ['color','#D2E5FF'] + }, + hover: { + border: ['color','#2B7CE9'], + background: ['color','#D2E5FF'] + } + }, + fixed: { + x: false, + y: false + }, + font: { + color: ['color','#343434'], + size: [14, 0, 100, 1], // px + face: ['arial', 'verdana', 'tahoma'], + background: ['color','none'], + stroke: [0, 0, 50, 1], // px + strokeColor: ['color','#ffffff'] + }, + //group: 'string', + hidden: false, + //icon: { + // face: 'string', //'FontAwesome', + // code: 'string', //'\uf007', + // size: [50, 0, 200, 1], //50, + // color: ['color','#2B7CE9'] //'#aa00ff' + //}, + //image: 'string', // --> URL + physics: true, + scaling: { + min: [10, 0, 200, 1], + max: [30, 0, 200, 1], + label: { + enabled: true, + min: [14, 0, 200, 1], + max: [30, 0, 200, 1], + maxVisible: [30, 0, 200, 1], + drawThreshold: [3, 0, 20, 1] + } + }, + shadow:{ + enabled: false, + size:[10, 0, 20, 1], + x:[5, -30, 30, 1], + y:[5, -30, 30, 1] + }, + shape: ['ellipse', 'box', 'circle', 'database', 'diamond', 'dot', 'square', 'star', 'text', 'triangle', 'triangleDown'], + size: [25, 0, 200, 1] + }, + edges: { + arrows: { + to: {enabled: false, scaleFactor: [1, 0, 3, 0.05]}, // boolean / {arrowScaleFactor:1} / {enabled: false, arrowScaleFactor:1} + middle: {enabled: false, scaleFactor: [1, 0, 3, 0.05]}, + from: {enabled: false, scaleFactor: [1, 0, 3, 0.05]} + }, + color: { + color: ['color','#848484'], + highlight: ['color','#848484'], + hover: ['color','#848484'], + inherit: ['from','to','both',true, false], + opacity: [1, 0, 1, 0.05] + }, + dashes: false, + font: { + color: ['color','#343434'], + size: [14, 0, 100, 1], // px + face: ['arial', 'verdana', 'tahoma'], + background: ['color','none'], + stroke: [1, 0, 50, 1], // px + strokeColor: ['color','#ffffff'], + align: ['horizontal', 'top', 'middle', 'bottom'] + }, + hidden: false, + hoverWidth: [2, 0, 5, 0.1], + physics: true, + scaling: { + min: [1, 0, 100, 1], + max: [15, 0, 100, 1], + label: { + enabled: true, + min: [14, 0, 200, 1], + max: [30, 0, 200, 1], + maxVisible: [30, 0, 200, 1], + drawThreshold: [3, 0, 20, 1] + } + }, + selectionWidth: [1.5, 0, 5, 0.1], + selfReferenceSize: [20, 0, 200, 1], + shadow:{ + enabled: false, + size:[10, 0, 20, 1], + x:[5, -30, 30, 1], + y:[5, -30, 30, 1] + }, + smooth: { + enabled: true, + dynamic: true, + type: ['continuous', 'discrete', 'diagonalCross', 'straightCross', 'horizontal', 'vertical', 'curvedCW', 'curvedCCW'], + roundness: [0.5, 0, 1, 0.05] + }, + width: [1, 0, 30, 1] + }, + layout: { + randomSeed: [0, 0, 500, 1], + hierarchical: { + enabled: false, + levelSeparation: [150, 20, 500, 5], + direction: ['UD', 'DU', 'LR', 'RL'], // UD, DU, LR, RL + sortMethod: ['hubsize', 'directed'] // hubsize, directed + } + }, + interaction: { + dragNodes: true, + dragView: true, + zoomView: true, + hoverEnabled: false, + navigationButtons: false, + tooltipDelay: [300, 0, 1000, 25], + keyboard: { + enabled: false, + speed: {x: [10, 0, 40, 1], y: [10, 0, 40, 1], zoom: [0.02, 0, 0.1, 0.005]}, + bindToWindow: true + } + }, + manipulation: { + enabled: false, + initiallyActive: false, + locale: ['en', 'nl'] + }, + physics: { + barnesHut: { + //theta: [0.5, 0.1, 1, 0.05], + gravitationalConstant: [-2000, -30000, 0, 50], + centralGravity: [0.3, 0, 10, 0.05], + springLength: [95, 0, 500, 5], + springConstant: [0.04, 0, 5, 0.005], + damping: [0.09, 0, 1, 0.01] + }, + repulsion: { + centralGravity: [0.2, 0, 10, 0.05], + springLength: [200, 0, 500, 5], + springConstant: [0.05, 0, 5, 0.005], + nodeDistance: [100, 0, 500, 5], + damping: [0.09, 0, 1, 0.01] + }, + hierarchicalRepulsion: { + centralGravity: [0.2, 0, 10, 0.05], + springLength: [100, 0, 500, 5], + springConstant: [0.01, 0, 5, 0.005], + nodeDistance: [120, 0, 500, 5], + damping: [0.09, 0, 1, 0.01] + }, + maxVelocity: [50, 0, 150, 1], + minVelocity: [0.1, 0.01, 0.5, 0.01], + solver: ['barnesHut', 'repulsion', 'hierarchicalRepulsion'], + timestep: [0.5, 0, 1, 0.05] + }, + selection: { + selectable: true, + selectConnectedEdges: true + }, + rendering: { + hideEdgesOnDrag: false, + hideNodesOnDrag: false + } +}; + + + + +export {allOptions, configureOptions}; \ No newline at end of file